CSP-S模拟赛四总结

T1

题面:

水题,但要注意内存只有 16MB16MB16MB!因此不能开数组后再排序。

(代码自己写。)

T2

题面:

首先这题很好想的办法就是用 dfs 暴力枚举每一个数可能的值,然后看一看最终答案多少。

代码:

int dfs(int la,int x,int sum)
{
   
   
	if(sum>m-1)
	{
   
   
		return 0;
	}
	if(x>n)
	{
   
   
		return c[n-1-sum][m-1-sum]%mod;
	}
	int ans=0; 
	for(int i=l[x];i<=r[x];i++)
	{
   
   
		if(i<=la)
		{
   
   
			ans=(ans+dfs(i,x+1,sum+1))%mod;
			ans%=mod;
		}
		else
		{
   
   
			ans=(ans+dfs(i,x+1,sum))%mod;
			ans%=mod;
		}
	}
	return ans%mod;
}

这样你就拿到了 10pts10pts10pts

然后我们在这个基础上套一个记忆化搜索,这样就可以拿到 50pts50pts50pts

int dfs(int la,int x,int sum)
{
   
   
	if(sum>m-1)
	{
   
   
		return 0;
	}
	if(x>n)
	{
   
   
		return c[n-1-sum][m-1-sum]%mod;
	}
	if(dp[la][x][sum]!=-1)
	{
   
   
		return dp[la][x][sum]%mod;
	}
	int ans=0; 
	for(int i=l[x];i<=r[x];i++)
	{
   
   
		if(i<=la)
		{
   
   
			ans=(ans+dfs(i,x+1,sum+1))%mod;
			ans%=mod;
		}
		else
		{
   
   
			ans=(ans+dfs(i,x+1,sum))%mod;
			ans%=mod;
		}
	}
	return dp[la][x][sum]=ans%mod;
}

现在我来讲一讲满分做法。

既然 dfs 行不通,那我们就倒过来,换成 DP。

因为 dfs 带了三个参数,所以这个 DP 肯定也会带三个参数,即设 dp[i][j][k] 表示当前在第 iii 个数字,上一个数字是 jjj 且目前已经分成了 kkk 段的方案数。

读者可以自行试一试这个 DP 的转移,总之我写出来是一个起步 O(n4)O(n^4)O(n4) 的 DP,而且没法优化。

因此我们可以试着改变一下 DP 的定义:设 dp[i][j][k] 表示第 iii 个位置选了 jjj 这个数且目前已经分成了 kkk 段的方案数。

然后我们就可以分类讨论了:

  1. 如果第 iii 位要与第 i−1i-1i1 位接上:那么前一个数必须小于 jjj,于是可以得出:dpi,j,k=∑p=1j−1dpi−1,p,kdp_{i,j,k}=\sum_{p=1}^{j-1}dp_{i-1,p,k}dpi,j,k=p=1j1dpi1,p,k
  2. 如果第 iii 位要单独开一段:那么前一个数就随便选了,于是可以得到:dpi,j,k=∑p=1400dpi−1,p,k−1dp_{i,j,k}=\sum_{p=1}^{400}dp_{i-1,p,k-1}dpi,j,k=p=1400dpi1,p,k1(这里为了方便直接把上限设成了最大)。

综上,可以得到状态转移方程:

dpi,j,k=∑p=1j−1dpi−1,p,k+∑p=1400dpi−1,p,k−1dp_{i,j,k}=\sum_{p=1}^{j-1}dp_{i-1,p,k}+\sum_{p=1}^{400}dp_{i-1,p,k-1}dpi,j,k=p=1j1dpi1,p,k+p=1400dpi1,p,k1

因为这个方程里面只涉及 iiii−1i-1i1 的值,所以可以用滚动数组优化,则得到:

dpx,j,k=∑p=1j−1dpx⊕1,p,k+∑p=1400dpx⊕1,p,k−1dp_{x,j,k}=\sum_{p=1}^{j-1}dp_{x\oplus1,p,k}+\sum_{p=1}^{400}dp_{x\oplus1,p,k-1}dpx,j,k=

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值