codeforces 839 D Winter is here
阿新 • • 發佈:2019-01-25
最後johsnows做jonsnow的題tle在了39...大概是因為我是假的snow吧。
這個題的想法挺套路的。
想法就是去列舉倍數,看有多少個數是當前這個數的倍數,這些數的gcd一定是當前這個數的倍數,假設有n個數,題目所求為gcd*k,列舉1<=i<=k,求出所有的C(i, n)*i,最後容次以下,去掉gcd是自己倍數的情況,就是以當前數位gcd的答案/gcd,容次之後乘回gcd就可以了。
注意求1-n的i*C(i,n)需要求一下公式,不能暴力求。
先把C(i,n)拆成階乘的形式,就可以看出來i*C(i,n)就是n*(i-1, n-1),所以最後求和就是n*2^(n-1)了。
也可以考慮求導。原式=[(1+x)^n]'=n(1+x)^(n-1)。
程式碼:
#include <bits/stdc++.h> #define LL long long using namespace std; const LL maxn=1e6+5; const int mod=1e9+7; int book[maxn]; LL a[maxn+5]; LL b[maxn]; LL c[maxn]; LL dp[maxn]; LL mmm; long long pw(long long a, long long b) { long long sum=1,base=a; while(b) { if(b&1)sum=(sum*base)%mod; base=(base*base)%mod; b>>=1; } return sum; } void init() { LL i, j; a[0]=1; for(i=1; i<=200005; i++) { a[i]=(a[i-1]*i)%mod; } } long long C(int m,int n) { long long sum=a[n]; // printf("%lld\n", sum); sum=sum*pw(a[n-m],mod-2)%mod; sum=sum*pw(a[m],mod-2)%mod; return sum; } int main() { int n; cin>>n; int i, j; LL ma=0; for(i=0; i<n; i++) { scanf("%lld", &b[i]); ma=max(ma, b[i]); book[b[i]]++; } memset(dp, -1, sizeof dp); LL ans=0; init(); for(i=2; i<=ma; i++) { LL sum=0; for(j=i; j<=ma; j+=i) { sum+=book[j]; } // printf("%d %lld\n", i, sum); LL g=i, y, z=0; int x=i; if(dp[sum]!=-1) { c[x]=(c[x]+dp[sum])%mod; continue; } if(sum==0)continue; z=(sum*pw(2LL, sum-1LL))%mod; c[x]=(c[x]+z)%mod; dp[sum]=z; } for(LL i=ma; i>=2; i--) { for(j=i+i; j<=ma; j+=i) { c[i]-=c[j], c[i]=(c[i]%mod+mod)%mod; } ans=(ans+(c[i]*i)%mod)%mod; } printf("%lld\n", ans); }