Connecting...

AT_tenka1_2014_final_a 解题报告

AT_tenka1_2014_final_a

前言:

怎么没有人发题解?我发一篇。玩了7天人废了,写了好久找不对初始状态。

思路

f[i][j]表示考虑第i种数字(0~h-1),已经有 j 个位置被确定了,现在用到 i 的方案数。

注意到 \(0\) 和别的数字有区别,作为初始状态,详见代码。状态转移方程详见代码。预处理阶乘逆元和阶乘就不讲了,大家都会。写这种简单dp的时候注意明确状态含义哦。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
using ll=long long;
const int maxn=2400,mod=1e9+7;
int n,h,w;
int fac[maxn+10],inv[maxn+10];
int f[maxn+10][maxn+10];//f[i][j]考虑第i种数字(0~h-1),已经有 j 个位置被确定了,现在用到 i 的方案数
ll qp(ll a,int b){
	ll res=1;
	while(b){
		if(b&1)res=1ll*res*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}return res;
}
ll C(int N,int M){
	if(M==0)return 1;
	if(N<M||N==0)return 0;
	return fac[N]*inv[M]%mod*inv[N-M]%mod;
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>h>>n>>w;
	fac[0]=1;
	for(int i=1;i<=maxn;++i)fac[i]=fac[i-1]*i%mod;
	inv[maxn]=qp(fac[maxn],mod-2);
	for(int i=maxn-1;i>=0;--i)inv[i]=inv[i+1]*(i+1)%mod;
	f[0][0]=1;
	for(int j=1;j<=n;++j)
		f[0][j]=C(w-1,j);
	for(int i=1;i<h;++i)
		for(int j=0;j<=w;++j)
			for(int k=0;k<=n&&j+k<=w;++k)
				(f[i][j+k]+=f[i-1][j]*C(w-j,k)%mod)%=mod;
	for(int i=0;i<h;++i)for(int j=0;j<=w;++j)cerr<<f[i][j]<<" \n"[j==w];
	cout<<f[h-1][w]<<"\n";
	return 0;
}
posted @ 2024-08-14 15:33  余亦宸  阅读(6)  评论(0)    收藏  举报