hdu 1695 GCD

来源:互联网 发布:幼儿园打卡软件 编辑:程序博客网 时间:2024/06/05 07:37

题目: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 100005int 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;}

原创粉丝点击