hdu 4135 Co-prime(容斥原理)
原创
©著作权归作者所有:来自51CTO博客作者胡桃小孩儿的原创作品,请联系作者获取转载授权,否则将追究法律责任
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4135
大意:求区间[a, b]内与n互质的数的个数。
分析:单纯来逐个判断互质统计结果肯定会超时,那么可以对n素因子分解,以素因子的个数作为循环的上界(第二层循环),第一层是枚举素因子,运用容斥原理来统计不互质的个数,最后再用总数减去不互质的个数就是互质的个数。【容斥原理也就是提供了这样间接求解的思想:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去。容斥原理是用来求多个集合的并集的一种方法: |S |= |奇数个集合的并集| - |偶数个集合的并集| (奇加偶减)这样
避开了用值很大的数字b作为循环上界,最后直接用b-a+1减去互质个数即可。二进制枚举,枚举的对象在第二层】
#include <iostream>
#include<cstdio>
using namespace std;
const int maxn=1e7+10;
typedef long long LL;
LL sta[maxn],top=0;
void fenjie(LL m){
top=0;
for(int i=2;i*i<=m;i++){
if(m%i==0){
sta[top++]=i;
while(m%i==0) m/=i;
}
}
if(m>1)sta[top++]=m;
}
int main()
{
//freopen("cin.txt","r",stdin);
LL t,ca=0;
LL A,B,N;
cin>>t;
while(t--){
scanf("%lld%lld%lld",&A,&B,&N);
fenjie(N);
LL ans=0;
for(int i=1;i<(1<<top);i++){
LL temp=1,sum=0;
for(int j=0;j<top;j++){
if(1<<j&i){
temp*=sta[j];
sum++;
}
if(temp>B)break;
}
if(sum&1)ans+=(B/temp-(A-1)/temp);
else ans-=(B/temp-(A-1)/temp);
}
printf("Case #%lld: %lld\n",++ca,B-A+1-ans);
}
return 0;
}