1. 程式人生 > >codeforce 839d.winter is here

codeforce 839d.winter is here

spa div amp 否則 scanf main oid stdio.h long long

題意:如果一個子序列的GCD為1,那麽這個子序列的價值為0,否則子序列價值為子序列長度*子序列GCD

給出n個數,求這n個數所有子序列的價值和

題解:首先得想到去處理量比較少的數據的貢獻,這裏處理每個gcd的貢獻。我們定義f(i)為gcd==i的倍數時的貢獻,那麽f(i)=c(0,n)*0+c(1,n)*1+...c(n,n)*n ,這裏的n為能夠整除i的數的個數。

然後結合c(1,n)+c(2,n)+....c(n,n)=2^n這個可以推出f(i)=n*2^(n-1)。然後倒著容斥一下(雖然自己看著別人的代碼看了半天,這裏還是裝逼帶過吧23333)。

ac代碼:

#include<stdio.h>  
#define
mod 1000000007 #define LL long long LL cnt[1000005], sum[1000005]; LL Pow(LL a, LL b) { LL now; now = 1; while(b) { if(b%2) now = now*a%mod; a = a*a%mod; b /= 2; } return now; } int main(void) { LL ans, i, j, n, x; scanf(
"%lld", &n); for(i=1;i<=n;i++) { scanf("%lld", &x); cnt[x]++; } ans = 0; // 註意轉換下題目意思 去枚舉每個gcd的貢獻 for(i=1000000;i>=2;i--) { x = 0; for(j=i;j<=1000000;j+=i) { sum[i] -= sum[j]; // 容斥 把倍數的結果去掉 x += cnt[j]; //
記錄gcd為x的個數 } sum[i] += x*Pow(2, x-1)%mod; // 組合公式 ans = ((ans+sum[i]*i)%mod+mod)%mod; } printf("%lld\n", ans); return 0; }

codeforce 839d.winter is here