一道不错的数论题,可惜自己想不出,只能参考大牛们的代码~~
http://acm.hdu.edu.cn/showproblem.php?pid=1695
#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define LL long long #define pi acos(-1) /*(1)题目要求gcd(x, y) = k , 可以转换为gcd(x / k , y / k) = gcd(n, m) = 1。相应地,题目中,x 和y的范围也可以相应地转换为[1, b / k] 和 [1, d / k]。 (2)题目中,x, y是无序的, 所以,我们可以假设b <= d。 (3)在[1, d / k] 中枚举每一个 m ,在[1, min(d / k, m - 1)]中找出和 m 互质的数的个数。 ①当 m <= b / k的时候,可以直接根据欧拉函数求出小于等于m且与m互质的数的个数。 ②当 b / k <= m <= d / k, 要用容斥原理来求。。。 */ #define N 100000+10 LL eul[N];//每个数的欧拉函数(包括之前所有的数) int num[N];//每个数的素因子有多少 int prim[N][50];//记录每个数的素因子 void EulerPrime() { int i,j,k; eul[1]=1; for(i=2;i<=N;i++) { if(eul[i]==0) {//凡进去的i都是质数 for(j=i;j<=N;j+=i) { if(eul[j]==0) eul[j]=j; eul[j]=eul[j]*(i-1)/i; prim[j][num[j]++]=i; }//cout<d) swap(b,d); LL ans=eul[b]; for(i=b+1;i<=d;i++) ans+=b-dfs(0,b,i); printf("Case %d: %I64d\n",t,ans); } } return 0; }