[ACG001E]BBQ Hard

ACG001E BBQ Hard

给定两个数组 求\(\begin{align*}\sum_{i=1}^n\sum_{j=i+1}^n\binom{a_i+b_i+a_j+b_j}{a_i+a_j} \end{align*}\)

由上面可以将\(\begin{align*}\binom{a_i+b_i+a_j+b_j}{a_i+a_j}\end{align*}\)转化为从点\((-b_i,-a_i)\)走到\((b_j,a_j)\)

\(f[i][j]\)即为各个起点走到它的方案数 递推可得

然后\(ans+=\sum_{i=1}^nf[a[i]][b[i]]\) 再减去自己走到自己的情况 最后除\(2\)

注意阶乘预处理要处理\(M<<2\)

==把组合变为走格子的形式很有用吖!

void Mod(ll &x){x=(x>=P)?x-P:x;}
ll C(int x,int y){return (fac[x]*ifac[y]%P)*ifac[x-y]%P;}
ll qpow(ll x,ll y){
    ll ret=1ll;
    while(y){
        if(y&1) ret=ret*x%P;
        x=x*x%P,y>>=1;
    }
    return ret;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
    rd(n);
    for(int i=1;i<=n;++i) rd(a[i]),rd(b[i]),++f[M-a[i]][M-b[i]];
    for(int i=1;i<=(M<<1);++i)
        for(int j=1;j<=(M<<1);++j)
            f[i][j]+=f[i-1][j],Mod(f[i][j]),f[i][j]+=f[i][j-1],Mod(f[i][j]);
    fac[0]=fac[1]=1ll;
    for(int i=2;i<=(M<<2);++i) fac[i]=fac[i-1]*(ll)i%P;
    ifac[M<<2]=qpow(fac[M<<2],P-2);
    for(int i=(M<<2);i;--i) ifac[i-1]=ifac[i]*i%P;
    for(int i=1;i<=n;++i) ans+=f[M+a[i]][M+b[i]],Mod(ans),ans+=(P-C(((a[i]+b[i])<<1),(a[i]<<1))),Mod(ans);
    printf("%lld",ans*inv2%P);
    return 0; 
}

你可能感兴趣的:([ACG001E]BBQ Hard)