题意:给定一个数列ai,若子序列长度为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 }
时间: 2024-12-26 08:26:21