uva 12716 GCD XOR (数论)枚举技巧(筛法) + 思维

来源:互联网 发布:随心安软件 编辑:程序博客网 时间:2024/06/01 19:17


uva 12716
题意:

输入整数n(1<=n<=3e7),有多少对整数(a,b)满足:1<=b<=a<=n,且gcd(a,b)=a XOR b。例如:n=7时,有4对:(3,2),(5,4),(6,4),(7,6)

思维:

确实是一个很不错的题目.
考虑到异或的性质,a xor b = c 那么 a xor c == b 一定成立.
那么对于上面这个题目我们可以枚举一个a和c,进而得到b.最后验证一下gcd(a,b) 是否等于c即可.
观察到因为要验证gcd,所以c肯定是a的因子,但如果暴力枚举因子复杂度a
所以这里我们有一点技巧.

用类似于筛法的方法,我们先枚举c,然后枚举a(这时候只需要枚举c的倍数即可),复杂度就是一个调和级数,nlogn。再加上gcd,所以最后复杂度为O(nlogn2)

我们发现还是会T(以后复杂度不满足的时候可以输出几个答案找找规律,没准可以优化)。
对于这个题目输出(a,c,b)三元组发现 b 恰好等于a - c,所以我们不需要做gcd了,只需要nlogn枚举c和a,然后b = a-c得到b,最后验证一下 a^b==c与否即可
然后预处理出1~n所有可能答案即可

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 3e7 + 5;ll n,ans[maxn];void init(){    ll up = maxn >> 1;    for(ll c = 1;c <= up;++c)    {        for(ll a = c + c;a < maxn ; a += c)//这里因为b不为0,所以a至少为c的二倍        {            ll b = a - c;            if((a ^ b) == c)            ans[a]++;        }    }    for(int i = 2;i < maxn;++i) ans[i] += ans[i-1];}int main(){    int _ ,ca = 1;    cin>>_;    init();    while(_--)    {        scanf("%lld",&n);        printf("Case %d: %lld\n",ca++,ans[n]);    }    return 0;}
原创粉丝点击