HDU 1695 GCD(phi函数+容斥)

来源:互联网 发布:淘宝信誉查询 淘一兔 编辑:程序博客网 时间:2024/05/19 08:03

Priblem Link

GCD
找出满足gcd(x,y)=k,x[1,b]y[1,d]的对数

Analyse

要找到满足gcd(x,y)=k,x[1,b]y[1,d]的解,相当于找gcdx/k,y/k=1,也就是说要找到gcd(x,y)=1,x[1,b/k],y[1,d/k]的对数,假设b<d
对于i[1,d/k],i<=b时,与i互素的个数就是,ϕ(i),而i>b用容斥原理找出[1,b/k]里面与i互素的个数就行了。

AC code

#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#define Debug(x) cout<<(x)<<endlusing namespace std;const int MAXN = 1e5+10;typedef long long LL;int prime[MAXN];int factor[MAXN];LL euler[MAXN];int primecnt;void getprime(){    primecnt=0;    memset(prime,0,sizeof(prime));    for(int i=2;i<MAXN;i++){        if(!prime[i])            prime[primecnt++]=i;        for(int j=0;j<primecnt && prime[j]<=MAXN/i;j++){            prime[prime[j]*i]=1;            if(i%prime[j] == 0)                break;        }    }}//求因子个数int getfactor(int n){    int factorcnt = 0;    for(int i=0 ; i<primecnt && prime[i] <= n/prime[i] ; ++i)    {        if(n%prime[i]==0)        {            factor[factorcnt++] = prime[i];            while(n % prime[i] == 0)n /= prime[i];        }    }    if(n>1)factor[factorcnt++] = n;    return factorcnt;}//与i互素的个数int uncoprime(int n,int x){    int factorcnt = getfactor(x);   // Debug(factorcnt);    int ans = 0;    for(int i = 1 ; i<(1<<factorcnt) ; ++i)    {        int cnt = 0,res = 1;        for(int j = 0 ; j<factorcnt ; ++j)        {            if(i & (1<<j)){                res*=factor[j];                cnt++;            }        }        if(cnt & 1)ans+=n/res;        else ans-=n/res;    }    //Debug(ans);    return ans;}void phi_table(int n = MAXN){    memset(euler,0,sizeof(euler));    euler[1] = 1;    for(int i=2 ; i<MAXN ; ++i)    {        if(!euler[i])        {            for(int j = i ; j<MAXN ; j+=i)            {                if(!euler[j])euler[j] = j;                euler[j] = euler[j]/i*(i-1);            }        }        euler[i]+=euler[i-1];    }}int main(){   //freopen("H:\\c++\\file\\stdin.txt","r",stdin);   int kase = 0;   int a,b,c,d,k;   int T;scanf("%d",&T);   getprime();   phi_table();   while(T--)   {       scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);       if(k>b|k>d || k ==0){        printf("Case %d: %d\n",++kase,0);continue;       }         b/=k;d/=k;       if(b>d)swap(b,d);       LL ans = euler[b];       for(int i= b+1 ; i<=d ; ++i)       {           ans  = ans+b-uncoprime(b,i);       }       printf("Case %d: ",++kase);       cout<<ans<<endl;   }    return 0;}
0 0
原创粉丝点击