您的位置:首页 > 其它

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

2017-10-09 00:10 232 查看
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
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: