Crash的游戏 [组合+递推]

题面

思路

问题转化

这个问题的核心在于,我们需要把“加入一个球、拿出一个球”这两个操作转化一下

因为显然两个操作同时进行的话,我们没有办法从单纯的组合意义去分析

我们首先把$m$个球拿出来,表示全部都选拿走球

然后对于我们选定的加入球的操作,我们一次性加入两个球

这样问题就变成了一个单纯加入球的问题了

左右分开

现在的问题是这样的:

给定$n-m$个球,你有$m$次机会,每次可以加入两个球,最后你会拿出$k$个球,问总方案数

我们把$k$个球的来源分开考虑

假设$k$个里面有$i$个来自于原来的$n-m$个球,$k-i$个来自于新加入的球

那么选出$i$个的方案数应该为$C^i_{n-m}$

后面新加入的球,我们考虑一个递推:$f[i][j]$表示从$i$对球中拿了东西,一共取出来了$j$个

那么新加入一对球,可以选择拿一个或者拿两个,因此可以写出方程

$g[i][j]=f[i-1][j-2]+f[i-1][j-1]*2$

计算答案

这个方程得到之后就好办了

我们先枚举$k$个里面从原来球中选出的个数,再枚举剩下的$k-i$用了多少对球($j$)

然后除了上面的两个东西要乘起来之外,还要再乘以$C{m}_j$和$2$,分别表示选出$j$对的方案,以及剩下的没有取出的东西做出的贡献

式子如下:

$Ans = \sum_{i=0}^k \sum_{j= \frac{k-i}{2} }^{k-i } C(n-m,i) \ast C(m,j) \ast 2^{m-j} \ast f[k-i][j]$

这里面的组合数每次询问单独处理,$f$数组可以预处理好,总复杂度$O(Tk^2)$

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define MOD 1000000007
using namespace std;
ll n,m,k,f[1010][1010],suf[510],suff[510],pre[510],C[510],CC[510],pw[510];
ll qpow(ll a,ll b){
	ll re=1;
	if(b<0) return 0;
	while(b){
		if(b&1) re=re*a%MOD;
		a=a*a%MOD;b>>=1;
	}
	return re;
}
void init(ll p,ll q){
	memset(C,0,sizeof(C));memset(CC,0,sizeof(CC));
	int i;C[0]=1;CC[0]=1;
	suf[1]=p;suff[1]=q;

	for(i=2;i<=min(p,k);i++) suf[i]=suf[i-1]*(p-i+1ll)%MOD;
	for(i=2;i<=min(q,k);i++) suff[i]=suff[i-1]*(q-i+1ll)%MOD;

	for(i=1;i<=min(p,k);i++) C[i]=suf[i]*pre[i]%MOD;
	for(i=1;i<=min(q,k);i++) CC[i]=suff[i]*pre[i]%MOD;
}
void getf(){
	int i,j,len=310;
	f[0][0]=1;
	for(i=1;i<=len;i++){
		for(j=1;j<=i*2;j++){
			f[i][j]=(f[i-1][j-1]*2+f[i-1][j-2])%MOD;
		}
	}
}
int main(){
	getf();int T;scanf("%d",&T);
	pre[1]=1;
	for(int i=2;i<=500;i++) pre[i]=(pre[i-1]*qpow(i,MOD-2))%MOD;
	while(T--){
		scanf("%lld%lld%lld",&n,&m,&k);
		init(n-m,m);
		ll ans=0,tmp;int i,j;
		for(i=0;i<=k;i++) pw[i]=qpow(2,m-i);
		for(i=0;i<=k;i++){
			tmp=0;
			for(j=(k-i+1)/2;j<=k-i;j++){
				(tmp+=CC[j]*pw[j]%MOD*f[j][k-i]%MOD)%=MOD;
			}
			(ans+=tmp*C[i]%MOD)%=MOD;
		}
		printf("%lld\n",ans);
	}
}
posted @ 2018-09-29 15:52  dedicatus545  阅读(227)  评论(0编辑  收藏  举报