容斥原理
Posted pangbi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了容斥原理相关的知识,希望对你有一定的参考价值。
题目链接:https://nanti.jisuanke.com/t/A1995
题意:给出递推式,我们可以算出a【n】=n*n+n;
那么Sn=n*(n+1)(2*n+1)/6+n*(n+1)/2;
我们有这样一个容斥定理:区间中与i不互质的个数=(区间中i的每个质因素的倍数个数)-(区间中i的每两个质因素的乘积的倍数个数)+
(区间中i的3个)-(4....)+(5....)-(6....)+(7.....)...... (偶数减,奇数加)
所以我们可以通过算出前n项和,再减去不互质的项的和,即为答案,
但是不互质的个数可能很多,一一枚举会导致超时,所以我们可以利用性质一次枚举多个;
假如我们枚举到某质因素乘积为k,那么根据原式可得,求得Sn为:
于是这道题就解决了
1 #include<queue> 2 #include<cstring> 3 #include<string> 4 #include<iostream> 5 #include<algorithm> 6 #include<cstdio> 7 #include<set> 8 using namespace std; 9 typedef long long ll; 10 const int maxn=100000; 11 const int mod=1e9+7; 12 ll mo(ll a,ll pp){ 13 if(a>=0&&a<pp)return a; 14 a%=pp; 15 if(a<0)a+=pp; 16 return a; 17 } 18 ll powmod(ll a,ll b,ll pp){ 19 ll ans=1; 20 for(;b;b>>=1,a=mo(a*a,pp)){ 21 if(b&1)ans=mo(ans*a,pp); 22 } 23 return ans; 24 } 25 26 ll inv1(ll b){ 27 return powmod(b,mod-2,mod); 28 } 29 bool check[maxn+7]; 30 int phi[maxn+7]; 31 int prime[maxn+7]; 32 int tot; 33 void phi_and_prime_table(int N) { 34 memset(check,false,sizeof(check)); 35 phi[1]=1; 36 tot=0; 37 for(int i=2; i<=N; i++) { 38 if(!check[i]) { 39 prime[tot++]=i; 40 phi[i]=i-1; 41 } 42 for(int j=0; j<tot; j++) { 43 if(i*prime[j]>N)break; 44 check[i*prime[j]]=true; 45 if(i%prime[j]==0) { 46 phi[i*prime[j]]=phi[i]*prime[j]; 47 break; 48 } 49 else{ 50 phi[i*prime[j]]=phi[i]*(prime[j]-1); 51 } 52 } 53 } 54 } 55 int p[107],dex[107]; 56 int getFactors(ll x) {//分解质因数 57 int fatcnt=0; 58 ll tmp=x; 59 for(int i=0; prime[i]<=tmp/prime[i]; i++) { 60 dex[fatcnt]=0; 61 if(tmp%prime[i]==0) { 62 p[fatcnt]=prime[i]; 63 while(tmp%prime[i]==0) { 64 dex[fatcnt]++; 65 tmp/=prime[i]; 66 } 67 fatcnt++; 68 } 69 } 70 if(tmp!=1) { 71 p[fatcnt]=tmp; 72 dex[fatcnt++]=1; 73 } 74 return fatcnt; 75 } 76 ll N; 77 ll S(ll x){ 78 ll n=N/x; 79 ll sum=(n*(n+1)%mod*(2*n+1)%mod)*inv1(6)%mod*x%mod*x%mod+n*(n+1)%mod*inv1(2)%mod*x%mod; 80 sum%=mod; 81 return sum; 82 } 83 int main() { 84 phi_and_prime_table(maxn); 85 ll m; 86 while(~scanf("%lld%lld",&N,&m)){ 87 int num=getFactors(m);//素因子个数 88 ll sum=S(1); 89 ll s=0; 90 for(int state=1;state<(1<<num);state++){//遍历所有状态 91 int tmp=1; 92 int cnt=0; 93 for(int i=0;i<num;i++){ 94 if(state&(1<<i)){ 95 cnt++; 96 tmp*=p[i]; 97 } 98 } 99 if(cnt&1){//容斥 100 s=(s+S(tmp))%mod; 101 } 102 else{ 103 s=(s-S(tmp)+mod)%mod; 104 } 105 106 } 107 sum=(sum+mod-s)%mod; 108 printf("%lld ",sum); 109 } 110 return 0; 111 } 112 ———————————————— 113 版权声明:本文为CSDN博主「别动我的白羊毛」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 114 原文链接:https://blog.csdn.net/yz467796454/article/details/82531727
以上是关于容斥原理的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 2393 Cirno的完美算数教室(容斥原理+搜索)