二項式定理做題記

无敌の暗黑魔王發表於2024-08-18

$\quad $ 主要式子:

\[(a+b)^{n} =\sum _{i=0}^{n}{C ^{i}_{n}}{a ^{i}b^{n-i}} \]

P10185 [YDOI R1] Necklace

$\quad $ 非常好的一道二項式定理入門題,我們不去考慮所有可能的項鍊對答案產生的貢獻,而是去考慮每種珠子對答案產生的貢獻。

$\quad $ 記 \(sum=\sum _{i=1}^{n}a_i\) ,那麼對於每種珠子,除這種珠子以外的情況一共有 \(2^{sum-a_i}\) 種。再看這種珠子產生的貢獻,應為 \(\sum _{x=1}^{n}{C _{a_i}^{x}}{v_i ^{x}}\)

$\quad $ 在後面補一項 \(1 ^{a_i -x}\) ,即為:

\[\sum _{x=1}^{n}{C ^{x} _{a_i}}{v_i ^{x} 1 ^{a_i -x}} \]

$\quad $ 然後就是一個裸的二項式定理(只不過去了一項 \(1\) ,加上再減去即可),就可以化為:

\[(v_i + 1)^{a_i} -1 \]

$\quad $ 所以最終答案為:

\[\sum _{i=1}^{n}{2 ^{sum -a_i}}[{(v_i +1) ^{a_i}-1] }] \]

$\quad $ 時間複雜度 \(O(nlog(sum))\)

點選檢視程式碼
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+100,p=1e9+7;
int v[N],a[N],n,ans;
int qum(int a,int b){
    int ans=1;
    while(b){
        (b&1)&&(ans=1ll*ans*a%p);
        a=1ll*a*a%p;
        b>>=1;
    }
    return ans;
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]),a[yhl]+=a[i];
    for(int i=1;i<=n;i++)scanf("%lld",&v[i]);
    for(int i=1;i<=n;i++)
        ans=(ans+1ll*qum(2,(a[yhl]-a[i]))*(qum(v[i]+1,a[i])-1+p)%p)%p;
    printf("%lld",ans);
    return yhl;
}

相關文章