UVA 12716 GCD XOR

来源:互联网 发布:简单力学分析软件 编辑:程序博客网 时间:2024/06/05 11:35

题意:求小于等于n的(a,b) 满足 a>b且 axorb=gac(a,b)的所以(a,b)数目 

n有30000000这么大  所以一直在想什么O(1)的算法 然而后来才发现 T放宽到5秒 还不限内存 Orz

设c为gcd(a,b) 而亦或的特性是 满足a^b=c 则 a^c=b。

所以我们可以枚举c 而a是c的倍数 所以可以再枚举a 再算出b=a^c 再检查是否满足 gcd(a,b)==c

而这题还有一个神奇的特性 即 若b满足 axorb=gac(a,b) 则 b一定为 a-gcd(a,b)

这样我们枚举出a,c 的时候 b=a-c 而这时gcd(a,b)是一定为c的  (原因同辗转相减法) 只需验证 是否a^b==c

时间复杂度O(nlogn)

#include<iostream>#include<cstdio>#include<cstring>#include<cctype>#include<cmath>#include<vector>#include<queue>#include<map>#include<algorithm>#include<set>#define scnaf scanf#define cahr char#define bug puts("bugbugbug");using namespace std;typedef long long ll;typedef unsigned long long ull;const int mod=1000000007;const int maxn=3e7+10;const int inf=1e9;int ans[maxn];int main(){    for(int n=1;n<maxn;n++)//n作为因子 即gcd(a,b)    {        for(int i=2;i*n<maxn;i++){            int a=i*n;            int b=a-n;            if( (a^b) == n) {                    ans[a]++;            }        }    }    for(int i=1;i<maxn;i++)       ans[i]+=ans[i-1];    int T_T,n,test=1;    scanf("%d",&T_T);    while(T_T--)    {        scanf("%d",&n);        printf("Case %d: %d\n",test++,ans[n]);    }    return 0;}


0 0