【DP】2018国庆三校联考D1T1

本文探讨了在有限格子内放置隔板的问题,通过分析不同隔板间距离限制,采用动态规划与组合数学方法求解方案数。具体介绍了DP状态转移方程及滑窗优化技巧,结合组合数计算总方案数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

在N个格子之间,放入D-1个隔板(可以重合),要求每两个相邻隔板之间距离不超过M。求方案数。
N,M≤2000N,M\leq 2000N,M2000
D≤1012D\leq 10^{12}D1012


分析:

尽管D的范围非常大,但其实很多隔板之间的距离都为0,所以可以考虑距离不为0的隔板的放置方案(即不能重合的方案)。再利用组合数求出在所有隔板中选择一定数量的方案数。

所以可以设DP(i,j)DP(i,j)DP(i,j)表示用i个格子,放置j各隔板,每两个之间距离不超过M的方案数。
这可以利用滑窗优化在O(n2)O(n^2)O(n2)范围内算出来。

然后组合数可以直接暴力求,复杂度也是O(n2)O(n^2)O(n2)的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 2010
#define MOD 998244353
using namespace std;
typedef long long ll;
ll dp[MAXN][MAXN];
ll fac[MAXN],ifac[MAXN];
int t;
ll n,m,d;
ll fsp(ll x,ll y){
	ll res=1;
	while(y){	
		if(y&1ll)
			res=res*x%MOD;
		x=x*x%MOD;
		y>>=1ll;
	}
	return res;
}
ll C(ll x,ll y){
	ll sum=1;
	for(ll i=x;i>x-y;i--){
		ll i1=i%MOD;
		sum=sum*i1%MOD;
	}
	sum=sum*ifac[y]%MOD;
	return sum;
}
int main(){
	fac[0]=1;
	for(ll i=1;i<=2000;i++)
		fac[i]=fac[i-1]*i%MOD;
	ifac[2000]=fsp(fac[2000],MOD-2);
	for(ll i=2000;i>=1;i--)
		ifac[i-1]=ifac[i]*i%MOD;
	while(SF("%lld%lld%lld",&n,&d,&m)!=EOF){
		if(n==0&&d==0&&m==0)
			break;
		m--;
		if(m==0){
			PF("%d\n",(n==0));
			continue;	
		}
		memset(dp,0,sizeof dp);
		dp[0][0]=1;
		for(int i=1;i<=n;i++){
			ll sum=dp[i-1][0];
			for(int j=1;j<=n;j++){
				dp[i][j]=sum;
				sum=(sum+dp[i-1][j])%MOD;
				if(j-m>=0)
					sum=(sum-dp[i-1][j-m]+MOD)%MOD;
			}
		}
		ll ans=0;
		for(int i=1;i<=n;i++)
			ans=(ans+C(d,i)*dp[i][n]%MOD)%MOD;
		PF("%lld\n",ans);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值