尤拉函式&&容斥原理
阿新 • • 發佈:2019-02-12
題意:給你五個數 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; }