演算法競賽高階指南筆記

2022-06-23 12:15:11 字數 4191 閱讀 7581

原碼

原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其餘位表示值. 比如如果是8位二進位制:

其中,第一位為1是負數

[+1] = [0000 0001]原

[-1] = [1000 0001]原

因此,8位二進位制數的取值範圍:[-127,127]

補碼正數的補碼是其本身

負數的補碼是在其原碼的基礎上,符號位不變,其餘各位取反,最後+1(即在其反碼的基礎上+1)

[+1] = [00000001]原 = [00000001]反 = [00000001]補

[-1] = [10000001]原 = [11111110]反 = [11111111]補

反碼

正數的反碼是其本身

負數的反碼是在其原碼的基礎上,符號位不變,其餘各個位取反

[+1] = [00000001]原 = [00000001]反

[-1] = [10000001]原 = [11111110]反

技巧

memset(a, 0x3f, sizeof(a))給陣列賦值 0x3f3f3f3f

賦值正無窮 inf = 0x3f3f3f3f 或者 inf = 0x3f

移位運算

左移:n << x = n*2^x

右移:n >> x = n/2^x (在c++中右移為算數右移,即移出去的位丟棄,空缺位用「符號位」來填充)

快速冪原理解釋:

**模板:

int qmi(int m, int k, int p)

return res;

}

例題:

acwing 89. a^b

#includeusing namespace std;

const int inf=0x3f3f3f3f;

typedef long long ll;

int main()

cout

與快速冪原理相同,將乙個乘數分解成二進位制來表示,然後再相乘,防止溢位。

#includeusing namespace std;

const int inf=0x3f3f3f3f;

typedef long long ll;

int main()

cout例題

acwing 92. 遞迴實現指數型列舉

位運算解法:

#includeusing namespace std;

const int inf=0x3f3f3f3f;

typedef long long ll;

int main()

if (temp == 0) cout << " " << endl;

else cout << endl;

}return 0;

}

遞迴解法:

#includeusing namespace std;

const int inf=0x3f3f3f3f;

typedef long long ll;

int n;

vectorres;

void solve(int x)

cout << endl;

return ;

}solve(x + 1);

res.push_back(x);

solve(x + 1);

res.pop_back();

}int main()

acwing 93. 遞迴實現組合型列舉

需要剪枝

#includeusing namespace std;

const int inf = 0x3f3f3f3f;

typedef long long ll;

int m,n;

vectorres;

bool vis[30];

void solve(int cnt)

cout << endl;

return ;

}for (int i = 1; i <= n; i++)

}}int main()

acwing 94. 遞迴實現排列型列舉

在上一題的基礎上修改一部分**就行

#includeusing namespace std;

const int inf = 0x3f3f3f3f;

typedef long long ll;

int n;

vectorres;

bool vis[30];

void solve(int cnt)

cout << endl;

return ;

}for (int i = 1; i <= n; i++)

}}int main()

acwing 99. 雷射炸彈

二維字首和

根據容斥原理,可以推導出二維字首和:s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]

#includeusing namespace std;

const int inf = 0x3f3f3f3f;

typedef long long ll;

int sum[5050][5050];

int n,r;

int main()

for (int i = 1; i <= 5001; i++)

for (int j = 1; j <= 5001; j++)

sum[i][j] += sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1];//以(0,0)為左下角的矩形求二維字首和

int ans = 0;

for (int i = r; i <= 5001; i++)

for (int j = r; j <= 5001; j++)

ans = max(ans, sum[i][j] - sum[i][j-r] - sum[i-r][j] + sum[i-r][j-r]);//因為炸彈影響r*r矩形的範圍,根據容斥原理同樣可以推導出ans=sum[i][j]-sum[i][j-r]-sum[i-r][j]+sum[i][j],最後再取乙個最大值就行

cout << ans

簡單的差分題,注意去重

#includeusing namespace std;

const int inf = 0x3f3f3f3f;

typedef long long ll;

int d[10005], res[10005];

set> vis;

int main()

)) continue;

vis.insert();

d[l + 1] --;

d[r] ++;

}res[0] = h;

for (int i = 1; i <= n; i++)

return 0;

}acwing 102. 最佳牛圍欄

二分出平均值,然後再用字首和找出該平均值條件下的最大子段和,在利用這個最大子段和來確定二分方向

#includeusing namespace std;

const int inf = 0x3f3f3f3f;

const double eps = 1e-5;

const int maxn = 1e6 + 50;

typedef long long ll;

int n, f;

double s[maxn], a[maxn], l, r, mid, ans, min_value;

int main()

if (ans >= 0) l = mid;

else r = mid;

}cout << (int)(r * 1000) << endl;

return 0;

}

演算法競賽高階指南學習筆記(2)

對頂棧 建立兩個棧 來動態維護序列中間的操作 類似對頂堆的思想 單調棧 棧內元素始終單調 排除不可能的選項 時間複雜度為o n 例題queue deque 單調佇列 單調佇列總不會寫 記得常練 cin n k for int i 1 i n i int head 1,tail 0 for int i...

《演算法競賽高階指南》 防曬

有c頭奶牛進行日光浴,第i頭奶牛需要minspf i 到maxspf i 單位強度之間的陽光。每頭奶牛在日光浴前必須塗防曬霜,防曬霜有l種,塗上第i種之後,身體接收到的陽光強度就會穩定為spf i 第i種防曬霜有cover i 瓶。求最多可以滿足多少頭奶牛進行日光浴。輸入格式 第一行輸入整數c和l。...

《演算法競賽高階指南》蚯蚓

蛐蛐國最近蚯蚓成災了!隔壁跳蚤國的跳蚤也拿蚯蚓們沒辦法,蛐蛐國王只好去請神刀手來幫他們消滅蚯蚓。蛐蛐國裡現在共有 n 只蚯蚓,第 i 只蚯蚓的長度為 ai 所有蚯蚓的長度都是非負整數,即可能存在長度為0的蚯蚓。每一秒,神刀手會在所有的蚯蚓中,準確地找到最長的那乙隻,將其切成兩段。若有多隻最長的,則任...