UVA-12716 GCD=XOR(枚举+预处理)

本文详细解析了UVA-12716题目,探讨了如何寻找满足特定条件的整数对(a,b),并分享了一种高效算法实现,将时间复杂度从O(n(logn)^2)优化到O(nlogn)。

传送门: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;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值