紫書題解彙總:[紫書CH0] 《算法競賽入門經典》(第2版) 題解目錄
1. 題目來源
2. 題目說明
中文描述:
3. 題目解析
方法一:數論+找規律+算法優化
例題10-5 GCD等於XOR(GCD XOR, ACM/ICPC Dhaka 2013, UVa12716)
按照書上的提示,記 ,那麼根據異或的性質來講,由 可得 ,那麼就可以通過枚舉 a
、c
計算得到 b
再驗證是否滿足 ,就能夠得到答案了。且由於 c
是 a
的約數,那麼就相同於素數篩算法了,那這個時間複雜度就爲 。gcd
時間複雜度爲 ,則總的時間複雜度爲 。
這個算法仍存在優化點有上述算法打印一些結果滿足 的三元組能夠發現規律爲 。關於這個規律的證明如下:不難發現 若存在 使得 ,則 ,與 矛盾。
那麼現在依舊枚舉 ,計算 ,則 ,因此僅驗證 即可,時間複雜度降爲 。
具體就是開闢兩個 MAXN = 30000000;
一個 cnt
用來放置當前 index
爲 a
時構成的滿足要求的整數對。第一層循環遍歷 c
第二層循環遍歷 a
由於滿足 c
一定是 a
的約數,所以 a
初始值可設爲 2c
步長增量也爲 c
。若滿足整數對條件,則 ++cnt[a]
。循環完畢後,統計整數 n
的整數對數,即需要將前面的 cnt
累加起來即可。
參見代碼如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
// 3e7 誤寫爲3e8時本地竟然無法通過,不能正常打印,2e8可以,3e8報鏈接錯誤
const int MAXN = 30000000;
int cnt[MAXN + 50], sum[MAXN + 50];
void solve() {
memset(cnt, 0, sizeof(cnt));
for (int c = 1; c <= MAXN; ++c) {
for (int a = c * 2; a <= MAXN; a += c) {
int b = a - c;
if (c == (a ^ b)) ++cnt[a];
}
}
sum[0] = 0;
for (int i = 1; i <= MAXN; ++i) sum[i] = sum[i - 1] + cnt[i];
}
int main() {
solve();
int T, n, tmp = 0;
cin >> T;
while (T--) {
scanf("%d", &n);
printf("Case %d: %d\n", ++tmp, sum[n]);
}
return 0;
}