1. 程式人生 > >[cf839d]Winter is here容斥原理

[cf839d]Winter is here容斥原理

win typedef ans frame spa 直接 review style cout

題意:給定一個數列ai,若子序列長度為k,最大公約數為gcd,定義子序列的權值為kgcd[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 }

[cf839d]Winter is here容斥原理