codeforce 839d.winter is here
阿新 • • 發佈:2017-08-23
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> #definemod 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