UVA-12716 GCD=XOR(枚舉+預處理)

傳送門:https://cn.vjudge.net/problem/UVA-12716

題意:

輸入整數n(1<=n<=30000000),有多少對整數(a,b)滿足:1<=b<=a<=n,且gcd(a,b)=a XOR b。例如n=7時,有4對:(3,2),(5,4),(6,4),(7,6)。

分析:

看上去很難,因爲gcd和xor似乎沒啥關聯。不過xor的好處是:a xor b=c,則a xor c=b。所以可以枚舉a和c,然後算出b=a xor c,最後驗證是否有gcd(a,b)=c。時間複雜度如何?約爲O(n(logn)^2)。

還可以優化。上述程序寫出來後,可以打印一些滿足gcd(a,b)=a xor b=c的三元組(a,b,c),然後很容易發現:c=a-b。

證明如下:不難發現a-b<=a xor b,且a-b>=c。假如存在c使得a-b>c,則c<a-b<=a xor b,這與c=a xor b矛盾。

於是時間複雜度降爲了O(nlogn)。

還有一個坑點,時間要求爲5s,需要預處理!!!

代碼:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll maxn=3e7+10;
ll f[maxn];
int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
} 
int main(){
	int t,n,a,b,c;
	memset(f,0,sizeof(f));
	for(c=1;c<=maxn/2;c++){
		for(a=2*c;a<maxn;a+=c){
			b=a-c;
			if((a xor b)==c){
				f[a]++;
			}
		}
	}
	for(int i=1;i<maxn;i++)
		f[i]+=f[i-1];
	scanf("%d",&t);
	for(int k=1;k<=t;k++){
		scanf("%d",&n);
		printf("Case %d: %lld\n",k,f[n]);
	}
	return 0;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章