1. 程式人生 > >尤拉函式&&容斥原理

尤拉函式&&容斥原理

題意:給你五個數 a,b,c,d,在[a,b]閉區間找一個數x,再在[c,d]閉區間中找一個數y,使得(x,y)的最大公約數是k。請找出所有滿足條件的不同(x,y)的對數。

1:因為我們知道gcd(x/k,y/k)=1,重新定義兩個區間[1,int(b/k]和[1,int(d/k)];

2:找兩個區間相互互質的就行了,假設b‘<d’,對於公共區間[1,b']可以通過尤拉函式累加和求出所有互質的。

3:對於[b'+1,d']則需要用容斥原理,從該區間任取x,則需要李勇容斥原理求[1,b']裡面有多少個和x不互質,再用b'來減

#include<iostream>
#include<cstdio>
using namespace std;
const int limit=100000;
struct Num{
     int count;
     int prime[16];
}N[limit+1];
__int64 elur[limit+1];
void ELUR()
{
    elur[1]=1;
    for(int i=0;i<=limit;i++)
        N[i].count=0;
    for(int i=2;i<=limit;i++)
    {
        if(!elur[i])
        {
            for(int j=i;j<=limit;j+=i)
            {
                if(!elur[j])
                    elur[j]=j;
                elur[j]=elur[j]*(i-1)/i;
                N[j].prime[N[j].count]=i;
                N[j].count++;

            }
        }
         elur[i]+=elur[i-1];
    }

}
__int64 Inclusion_exclusion(int index,int b,int n)
{
    __int64 r=0,t;
    for(int i=index;i<N[n].count;i++)
    {
        t=b/N[n].prime[i];
        r+=t-Inclusion_exclusion(i+1,t,n);
    }
    return r;
}
int main()
{
    int t,a,b,c,d,num=0,k;
    __int64 ans;
    ELUR();
    scanf("%d",&t);
    while(t--)
    {
        num++;
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        if(k==0)
        {
            printf("Case %d: 0\n",num);
            continue;
        }
        if(b>d)
        {
            b^=d;
            d^=b;
            b^=d;
        }
        b=b/k; //gcd(x/k,y/k)==1
        d=d/k;
        ans=elur[b];
        for(int i=b+1;i<=d;i++)
        {
            ans+=b-Inclusion_exclusion(0,b,i);
        }
        printf("Case %d: %I64d\n",num,ans);
    }
    return 0;
}