[COCI2009-2010#4] KABOOM

[COCI2009-2010#4] KABOOM

考虑 dpi,jdp_{i,j} 表示长度为 ii ,前 jj 个段全部都是胶的方案总数。

这个方程显然适用于左边和右边。

我们以左边举例。

首先,如果翻折了且合法的话的话,翻完以后上边和下边显然都是有胶水的。

我们不可以从 ii 往前面翻折,因为这个 ii 是后面决策的中间部分,我们不可能从中间往前面翻折,所以我们考虑从 11 往后翻折。

上面这张图就比较清晰了,翻折完以后还是两面带胶的,相当于最开始 a,ba,b 那一些段。

如上面这张图,表示的是把 11kk 这一段往后面翻折,就可以得到 dpik,kdp_{i-k,k} 这个状态,说明 dpik,k+=dpi,jdp_{i-k,k}+=dp_{i,j},我们要严格使得翻折以后不能超过 ii,所以 kk 应该在 [j,i/2][j,i/2] 之间。

但是这样的时间复杂度比较大,我们考虑优化。

由于我们采用的是翻折的操作,我们考虑从某个点翻开,也就是逆推的思路,首先要知道,逆推的思路是绝对不会对最后答案有任何影响的。

通过当前的 dpi,jdp_{i,j},就相当于枚举 kk,去进行翻开,对于 dpi,jdp_{i,j} 统计这个值。

在对于求和的时候,也就是翻开的时候,这时候的 kk 是在 [j,i][j,i] 之间的。(从 ii 翻开,同时不能和前面 jj 个东西粘起来。)

然后我们就发现,这个和前面的 [j+1,i][j+1,i] 的这个区间(表示的是 dpi,j+1dp_{i,j+1})这个区间表示的值是差了一个 k=jk=j 的情况,那么就是 dpij,jdp_{i-j,j} 了。

所以就有方程:

dpi,j=dpi,j+1+dpij,jdp_{i,j}=dp_{i,j+1}+dp_{i-j,j}

在最后统计和的时候,由于公式是非严格的,也就是说要用 dp[i][a]dp[i1][a]dp[i][a]-dp[i-1][a] 来表示左边严格折到 ii 时的方案数(这样可以保证不会统计重复),所以对于 ainba \leq i \leq n-b 来说(两面有胶的是不能翻折的),就有

(dp[i][a]dp[i1][a])×dp[ni][b](dp[i][a]-dp[i-1][a])\times dp[n-i][b]

最后输出答案就结束了。

Code:Code:

#include<bits/stdc++.h>
using namespace std;
const int N =2000;
const int mod=10301;
int dp[N][N];
int main()
{
	int n,a,b;
	cin>>n>>a>>b;
	for(int i=0;i<n;i++)
		dp[i][i]=1;
	for(int i=0;i<n;i++)
		for(int j=i-1;j>=1;j--)
			dp[i][j]=(dp[i][j+1]+dp[i-j][j])%mod;
	int ans=0;
	for(int i=a;i<=n-b;i++)
		(ans+=(((dp[i][a]+mod-dp[i-1][a])%mod)*dp[n-i][b]%mod)%mod)%=mod;
	cout<<ans<<endl;
}
posted @   June_Failure  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示