题目:GCD hdu 1695 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 题意:Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k;给出abcdk五个数,求满足GCD(x, y) = k的x,y的种数。其中x满足在区间a...b内,y满足在区间c...d内; 解题思路:GCD(x, y) = k可以进行转换为GCD(x/k, y/k) = 1;在区间1...b/k与1...d/k内取小的那个求出在小一点的区间内互质的个数,再求在小区间内与大区间减去小区间的数中满足条件的个数。利用欧拉与容斥来进行两步的解决 AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define LL long long #define maxn 100005 int x[maxn],cnt[1005]; int euler_phi(int n) { int m = (int)sqrt(n+0.5); int ans = n; for(int i = 2; i <= m; i++) { if(n%i==0) { ans = ans/i*(i-1); while(n%i==0) n/=i; } } if(n>1) ans = ans/n*(n-1); return ans; } LL Imco_prime(int n,int m) { int i,j,t=0; for(i=2; i*i<=n; i++) { if(n&&n%i==0) { cnt[t++]=i; while(n&&n%i==0) n/=i; } } if(n>1) cnt[t++]=n; LL ans=0,tmp,flag; for(i=1; i<(1<<t); i++) { tmp=1,flag=0; for(j=0; j<t; j++) if(i&(1<<j)) flag++,tmp*=cnt[j]; if(flag&1) ans+=m/tmp; else ans-=m/tmp; } return ans; } int main() { int T,t=0,a,b,c,d,k,i; scanf("%d",&T); while(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=0,tmp=(LL)b*(d-b); for(i=1; i<=b; i++) ans+=euler_phi(i); for(i=b+1; i<=d; i++) tmp-=Imco_prime(i,b); printf("Case %d: %I64d\n",++t,ans+tmp); } return 0; }