[紫書CH10] 例題10-5:GCD等於XOR(數論、找規律、算法優化、UVa12716)

紫書題解彙總:[紫書CH0] 《算法競賽入門經典》(第2版) 題解目錄

1. 題目來源

鏈接:UVA12716 GCD XOR

2. 題目說明

在這裏插入圖片描述

中文描述:

在這裏插入圖片描述

3. 題目解析

方法一:數論+找規律+算法優化

例題10-5 GCD等於XOR(GCD XOR, ACM/ICPC Dhaka 2013, UVa12716)

按照書上的提示,記 gcd(a,b)=ab=cgcd(a,b)=a\oplus b =c,那麼根據異或的性質來講,由 ab=ca\oplus b =c 可得 ac=ba \oplus c =b,那麼就可以通過枚舉 ac 計算得到 b 再驗證是否滿足 gcd(a,b)=cgcd(a,b)=c,就能夠得到答案了。且由於 ca 的約數,那麼就相同於素數篩算法了,那這個時間複雜度就爲 i=1nni=O(nlogn)\sum_{i=1}^n\frac{n}{i}=O(nlogn)gcd 時間複雜度爲 O(logn)O(logn),則總的時間複雜度爲 O(n(logn)2)O(n(logn)^2)

這個算法仍存在優化點有上述算法打印一些結果滿足 gcd(a,b)=ab=cgcd(a,b)=a\oplus b =c 的三元組(a,b,c)(a,b,c)能夠發現規律爲 c=abc=a-b。關於這個規律的證明如下:不難發現 abababca-b\leq a \oplus b 且 a-b \geq c 若存在 cc 使得 ab>ca-b>c,則 c<ababc <a-b \leq a \oplus b,與 c=abc=a \oplus b 矛盾。

那麼現在依舊枚舉 aca、c,計算 b=acb=a-c,則 gcd(a,b)=gcd(a,ac)=cgcd(a,b)=gcd(a,a-c)=c,因此僅驗證 c=abc= a \oplus b 即可,時間複雜度降爲 O(nlogn)O(nlogn)

具體就是開闢兩個 MAXN = 30000000; 一個 cnt 用來放置當前 indexa 時構成的滿足要求的整數對。第一層循環遍歷 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章