题意
找出[a,b]中与n互质的数的个数
分析
通常我们求1~n中与n互质的数的个数都是用欧拉函数.但如果n比较大或者是求1~m中与n互质的数的个数等等问题,要想时间效率高的话还是用容斥原理。先对n分解质因数,分别记录每个质因数, 那么所求区间内与某个质因数不互质的个数就是 m/r(i),假设r(i)是r的某个质因子 假设只有三个质因子, 总的不互质的个数应该为p1+p2+p3-p1*p2-p1*p3-p2*p3+p1*p2*p3. pi代表m/r(i),即与某个质因子不互质的数的个数 ,当有更多个质因子的时候,可以用状态压缩解决,二进制位上是1表示这个质因子被取进去了。 如果有奇数个1,就相加,反之则相减
容斥原理
求事件A、B、C的交集时,A U B U C=A+B+C-AB-AC-BC+ABC。
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define ll long long #define ull unsigned long long #define LOCAL using namespace std; const int maxn=5000+10; const int inf=0x3f3f3f3f; const int mod=1e9+7; vector<ll> v; ll a,b,n; void getPrime(ll n){//素数分解,要求的n较少时 v.clear(); for(ll i = 2;i*i<=n;i++){ if(n%i==0){ v.push_back(i); while(n%i==0) n/=i; } } if(n>1) v.push_back(n); return ; } ll solve(ll x,ll n){ getPrime(n); ll sum=0,val,cnt; for(ll i=1;i<(1<<v.size());i++){ val=1; cnt=0; for(ll j=0;j<v.size();j++){ if((1<<j)&i){ val*=v[j]; cnt++; } } if(cnt&1) sum+=x/val; else sum-=x/val; } return x-sum; } int main(){ int t; scanf("%d",&t); for(int i=1;i<=t;i++){ cin>>a>>b>>n; printf("Case #%d: %I64d\n",i,solve(b,n)-solve(a-1,n)); } return 0; }