一道不錯的數論題,可惜自己想不出,只能參考大牛們的代碼~~
http://acm.hdu.edu.cn/showproblem.php?pid=1695
#include<iostream>#include<vector>#include<map>#include<stack>#include<algorithm>#include<queue>#include<list>#include<set>#include<string.h>#include<stdlib.h>#include<math.h>#include<stdio.h>#include<ctype.h>#include<iomanip>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+10LL 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<<i<<endl; } eul[i]+=eul[i-1]; }}LL dfs(int index,int res,int cur)//計算小於等於res的數中,與cur不互質的個數{ LL ret=0; int i; for(i=index;i<num[cur];i++)//容斥原理來求A1並A2並A3.....並Ak的元素的數的個數.(還不是很懂!) { //printf("%d/%d=%d\n",res,prim[cur][i],res/prim[cur][i]); ret+=res/prim[cur][i]-dfs(i+1,res/prim[cur][i],cur); } return ret;}int main(){ // freopen("a.txt","r",stdin); int a,b,c,d,k; int ca; int i,j,t; EulerPrime();//預先處理 while(scanf("%d",&ca)!=EOF) { for(t=1;t<=ca;t++) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); if(k==0) { printf("Case %d: 0\n",t); continue; } b/=k; d/=k; if(b>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;}