返回顶部

二项式定理做题记

$\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;
}
posted @ 2024-08-18 15:33  无敌の暗黑魔王  阅读(20)  评论(0编辑  收藏  举报