UVA

来源:互联网 发布:合肥培训软件 编辑:程序博客网 时间:2024/06/17 18:01

题目链接:https://vjudge.net/problem/UVA-12716

题目大意:求出1<=b<=a<=n的二元组(a,b),使得gcd(a,b)=a^b

解题思路:因为有^,所以应该先想到^对应的性质,即a^b^a=b,所以a^gcd(a,b)=a^a^b=b,由于gcd(a,b)必定是a的因子,所以只用枚举a的因子,求出相应的b之后检验gcd(a,b)是否与之前的相同。接着进行优化,首先要知道几个结论,假设a>b,1.a-b>=gcd(a,b)
证明:
因为a=t1*gcd(a,b),b=t2*gcd(a,b),所以a-b=(t1-t2)*gcd(a,b)>=gcd(a,b)
2.a-b<=a^b
证明:把a和b都先转化成二进制,然后把a中的0与b中的1互换,得到a1,b1,并且a1>=a,b1<=b,并且可以发现a1-b1=a1^b1(这个我不会证明),所以a1^b1=a^b>=a-b
综上,a-b=a^b=gcd(a,b)
所以在枚举因子时不需要调用函数求gcd(a,b),直接相减即为gcd(a,b)
但是,做到这里还是会超时,要进行预处理,对于每个二元组中的a,都可以记录a所具有的b的个数,然后一直向上累加,就可以得到小于等于n的总个数,然后直接输出即可

AC代码:

#include<cstdio>#include<iostream>using namespace std;typedef long long LL;const int MAXN = 30000000 + 5;int ans[MAXN];int main(){    for (int i = 1;i < MAXN;i++)    {        for (int j = i;j < MAXN;j += i)        {            int b = i^j;            if (b <= j&&b >= 1 && j - b == i)                ans[j]++;        }    }    for (int i = 2;i < MAXN;i++)        ans[i] += ans[i - 1];    int t;scanf("%d", &t);    for(int p=1;p<=t;p++)    {        int n;scanf("%d", &n);        printf("Case %d: %d\n", p, ans[n]);    }    return 0;}
原创粉丝点击