HDU1695 GCD (欧拉函数+容斥原理)
Posted Ritchie丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU1695 GCD (欧拉函数+容斥原理)相关的知识,希望对你有一定的参考价值。
求(1,b)区间和(1,d)区间里面gcd(x, y) = k的数的对数(1<=x<=b , 1<= y <= d)。
b和d分别除以k之后的区间里面,只需要求gcd(x, y) = 1就可以了,这样子求出的数的对数不变。
这道题目还要求1-3 和 3-1 这种情况算成一种,因此只需要限制x<y就可以了
只需要枚举x,然后确定另一个区间里面有多少个y就可以了。因此问题转化成为区间(1, d)里面与x互素的数的个数
先求出x的所有质因数,因此(1,d)区间里面是x的质因数倍数的数都不会与x互素,因此,只需要求出这些数的个数,减掉就可以了。
如果w是x的素因子,则(1,d)中是w倍数的数共有d/w个。
容斥原理:
所有不与x互素的数的个数= 1个因子倍数的个数 - 2个因子乘积的倍数的个数 + 3个……-……
答案很大,用long long。
所有数的素因子,预先处理保存一下,不然会超时的。
#include<iostream> using namespace std; const int Max=100005; __int64 elur[Max];//存放每个数的欧拉函数值 int num[Max];//存放数的素因子个数 int p[Max][20];//存放数的素因子 void init()//筛选法得到数的素因子及每个数的欧拉函数值 { elur[1]=1; for(int i=2;i<Max;i++) { if(!elur[i]) { for(int j=i;j<Max;j+=i) { if(!elur[j]) elur[j]=j; elur[j]=elur[j]*(i-1)/i; p[j][num[j]++]=i; } } elur[i]+=elur[i-1]; //进行累加(法里数列长度) } } int dfs(int idx,int b,int now)//求不大于b的数中,与now不互质的数的个数; { //dfs()写的容斥原理 int ans=0; for(int i=idx;i<num[now];i++)//容斥原理来求A1并A2并A3.....并Ak的元素的数的个数. ans += b/p[now][i]-dfs(i+1,b/p[now][i],now); return ans; } int main() { int t,a,b,c,d,k; init(); scanf("%d",&t); for(int ca=1;ca<=t;ca++) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); printf("Case %d: ",ca); if(k==0) { printf("0\n"); continue; } if(b>d) swap(b,d); b/=k; d/=k; __int64 ans=elur[b]; for(int i=b+1;i<=d;i++) ans+=b-dfs(0,b,i);//求不大于b的数中,与i不互质的数的个数 printf("%I64d\n",ans); } return 0; }
以上是关于HDU1695 GCD (欧拉函数+容斥原理)的主要内容,如果未能解决你的问题,请参考以下文章