ARC061F题解
来考虑一件事情
把打牌的顺序串起来,这肯定是一条长度为 \(N+M+K\) 的链。
然后相当于是在这个序列上面填数。\(A\) 胜利的条件就是有一个前缀有 \(n\) 个 \(a\),且 \(b,c\) 的数量分别不超过 \(m,k\)。并且容易发现一个序列肯定只对应一种牌序。
第一件事肯定是枚举这个前缀。先用组合数把 \(a\) 塞进去。假设前缀的长度是 \(i\),那么还剩下 \(i-n\) 个位置。
这是一个二维背包。但是直接计算有点儿慢,考虑组合数。
会寄掉只可能是其中一个出现了至少 \(m+1\) 或 \(k+1\) 次。
\[\sum_{x=m+1}^{i-n}\binom{i-n}{x}+\sum_{x=k+1}^{i-n}\binom{i-n}{x}
\]
那么答案就是:
\[\sum_{i=n}^{n+m+k}\binom{i}{n}(2^{i-n}-\sum_{x=m+1}^{i-n}\binom{i-n}{x}-\sum_{x=k+1}^{i-n}\binom{i-n}{x})3^{n+m+k-i}
\]
我们设 \(f[x]=\sum_{i=m}^{x}\binom{x}{i}\)。
考虑这个东西:
\[f[x]=\sum_{i=m}^{x}\binom{x-1}{i}+\binom{x-1}{i-1}
\]
\[f[x]=f[x-1]+f[x-1]+\binom{x-1}{m-1}
\]
然后就 \(O(n+m+k)\) 了。。。
#include<cstdio>
typedef unsigned ui;
const ui M=1e6,mod=1e9+7;
ui A,B,C,F[M],G[M],pw2[M],pw3[M],fac[M],ifac[M];
inline ui binom(const ui&n,const ui&m){
return 1ull*ifac[m]*ifac[n-m]%mod*fac[n]%mod;
}
signed main(){
ui ans(0);scanf("%u%u%u",&A,&B,&C);
pw2[0]=1;pw3[0]=1;fac[0]=1;ifac[0]=1;
pw2[1]=2;pw3[1]=3;fac[1]=1;ifac[1]=1;
for(ui i=2;i<=A+B+C;++i){
pw2[i]=2ull*pw2[i-1]%mod;pw3[i]=3ull*pw3[i-1]%mod;ifac[i]=1ull*(mod-mod/i)*ifac[mod%i]%mod;
}
for(ui i=2;i<=A+B+C;++i)fac[i]=1ull*fac[i-1]*i%mod,ifac[i]=1ull*ifac[i-1]*ifac[i]%mod;
for(ui i=B+1;i<=A+B+C;++i)F[i]=(2ull*F[i-1]+binom(i-1,B))%mod;
for(ui i=C+1;i<=A+B+C;++i)G[i]=(2ull*G[i-1]+binom(i-1,C))%mod;
for(ui i=A;i<=A+B+C;++i)ans=(ans+1ull*binom(i-1,A-1)*(pw2[i-A]+mod-F[i-A]+mod-G[i-A])%mod*pw3[A+B+C-i])%mod;
printf("%u",ans);
}