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);
}
posted @ 2022-04-28 09:51  Prean  阅读(32)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};