傳送門: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;
}