HDU 4135 Co-prime 容斥原理
Posted legend_PawN
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4135 Co-prime 容斥原理相关的知识,希望对你有一定的参考价值。
题目链接
统计在大区间[A,B]中与N互质的数的个数,其中A,B都在10的15次方级。
暴力肯定不行,正难则反,思考求[A,B]中不与N互质的数的个数,那么该数必然是N的其中一个因子的倍数,所以首先对N的所有因子进行打表,然后根据每一个因子求在[A,B]区间中其倍数的个数。
在不同的因子进行计数的时候可能产生重复,所以进行容斥。
最后,小技巧将区间转化成[1,B]-[1,A-1]求更加方便。
两种容斥的形式:
vis[i]-num[i]通用型:
AC代码:
#include <bits/stdc++.h>
typedef long long ll;
const int N=1e5;
using namespace std;
ll a,b,n;
int p[N];
int num[N],vis[N];
int main()
int T,cnt=0;
scanf("%d",&T);
while(T--)
memset(num,0,sizeof(num));
memset(vis,0,sizeof(vis));
scanf("%lld%lld%lld",&a,&b,&n);
int count=0;
for(int i=1;i*i<=n;i++)
if(n%i==0)
p[count++]=i;
if(i*i!=n)
p[count++]=n/i;
sort(p,p+count);
for(int i=0;i<count;i++)
vis[i]=1;
vis[0]=0;
ll ans=0;
for(int i=0;i<count;i++)
ans+=1LL*(b/p[i]-(a-1)/p[i])*(vis[i]-num[i]);
ll tmp=vis[i]-num[i];
for(int j=i;j<count;j++)
if(p[j]%p[i]==0)
num[j]+=tmp;
printf("Case #%d: %lld\\n",++cnt,b-a+1-ans);
return 0;
二进制状态压缩容斥原理:
AC代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
ll co_prime(ll n, ll m)//求1-m中有多少个数与n互质
ll ret=0; //结果
vector <ll> prime;
prime.clear();
ll i,j;
for(i=2;i*i<=n;i++)
if(n%i==0)
prime.push_back(i);
while(n%i==0)
n/=i;
if(n>1)
prime.push_back(n);
ll len=(1<<prime.size())-1; //状态压缩的所有状态数
ll cnt, t;
for(i=1;i<=len;i++)
t=1;
cnt=0;
for(j=0;j<prime.size();j++)
if(i&(1<<j))
t*=prime[j];
cnt++;
if(cnt&1)
ret+=m/t;
else
ret-=m/t;
return m-ret;
int main()
//freopen("input.txt","r",stdin);
int T;
int cases=1;
scanf("%d",&T);
while(T--)
ll a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
printf("Case #%d: ", cases++);
printf("%lld\\n",co_prime(c,b)-co_prime(c,a-1));
return 0;
以上是关于HDU 4135 Co-prime 容斥原理的主要内容,如果未能解决你的问题,请参考以下文章