[cf839d]Winter is here容斥原理
题意:给定一个数列${a_i}$,若子序列长度为$k$,最大公约数为$gcd$,定义子序列的权值为$k*\gcd (\gcd > 1)$。求所有子序列的权值和。 答案对10^9+7取模。
解题关键:容斥原理求序列中各$gcd$的个数,亦可用莫比乌斯函数。
逆序求的话,前面直接减后面的个数,在后面一项就相当于相加了,如此往复。
关于知道所有$gcd$为$n$的个数之后答案的求法:
法一:
$\begin{array}{l}
1C_n^1 + 2C_n^2 + ... + nC_n^n\\
= n(C_{n - 1}^1 + C_{n - 1}^2 + ... + C_{n - 1}^{n - 1})\\
= n{2^{n - 1}}
\end{array}$
法二:
$\begin{array}{l}
[{(x + 1)^n}]' = n{(x + 1)^{n - 1}}\\
{(x + 1)^n} = \sum\limits_{i = 1}^n {C_n^i{x^i}} \\
n{(x + 1)^{n - 1}} = \sum\limits_{i = 1}^n {C_n^ii{x^{i - 1}}}
\end{array}$
法三:逆序相加
容斥解法:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int mod=1e9+7; 5 #define inf 0x3f3f3f3f 6 ll c[1000004],pw[1000007],sum[1000007]; 7 int main(){ 8 ll n,x,mx=-inf; 9 cin>>n; 10 pw[0]=1; 11 for(int i=1;i<=n+3;i++) pw[i]=pw[i-1]*2%mod; 12 for(int i=0;i<n;i++) cin>>x,c[x]++,mx=max(mx,x);//hash一下 13 ll ct; 14 ll ans=0; 15 for(int i=mx;i>1;i--){ 16 ct=0; 17 for(int j=i;j<=mx;j+=i){ 18 ct=(ct+c[j])%mod; 19 sum[i]-=sum[j]; 20 } 21 sum[i]=(sum[i]+ct*pw[ct-1]%mod+mod)%mod; 22 ans=(ans+sum[i]*i%mod+mod)%mod; 23 } 24 cout<<ans<<"\n"; 25 return 0; 26 }
莫比乌斯反演解法:
1 #include<bits/stdc++.h> 2 #define inf 0x3f3f3f3f 3 using namespace std; 4 typedef long long ll; 5 const int mod=1e9+7; 6 ll mu[1000020],c[1000060],cnt[1000050],pw[1000050],g[1000050]; 7 void sievemu(int n){ 8 mu[1]=1; 9 for(int i=1;i<=n;i++){ 10 for(int j=i+i;j<=n;j+=i){ 11 mu[j]-=mu[i]; 12 } 13 } 14 } 15 16 int main(){ 17 sievemu(1000005); 18 ll n,x,mx=-inf; 19 cin>>n; 20 pw[0]=1; 21 for(int i=1;i<=n;i++) pw[i]=pw[i-1]*2%mod; 22 for(int i=0;i<n;i++) cin>>x,c[x]++,mx=max(mx,x); 23 for(int i=2;i<=mx;i++){ 24 ll ss=0; 25 for(int j=i;j<=mx;j+=i){ 26 ss+=c[j]; 27 } 28 if(ss) cnt[i]=ss*pw[ss-1]%mod; 29 } 30 //计算gcd倍数的个数 31 32 //对答案进行莫比乌斯反演 33 ll ans=0; 34 for(int i=2;i<=mx;i++){ 35 for(int j=i;j<=mx;j+=i){ 36 g[i]=(g[i]+cnt[j]*mu[j/i]%mod+mod)%mod; 37 } 38 ans=(ans+i*g[i]%mod+mod)%mod; 39 } 40 cout<<ans<<"\n"; 41 return 0; 42 }