……

解题报告: CF1288C

题目链接:CF1288C Two Arrays
\(dp\)被暴切了,真开心<-睿智\(xxs\)
本题有\(\mathcal O(n+m),\mathcal O(nm),\mathcal O(n^2m)\)的做法,当然我一眼只能切出\(\mathcal O(nm)\)的做法,不过\(\mathcal O(n+m)\)应该也是可做的。
看到题目很多限制,不禁慌乱,不过自己写一写很快发现满足:

\[a_1\leqslant a_2\leqslant ......\leqslant a_n\leqslant b_n\leqslant b_{n-1}\leqslant b_1 \]

然后用\(dp\)来动态更新组合数即可,大概是这样的:
我们设\(dp[i][j]\)为第\(i\)小位置上结尾数(及最大数)为\(j\)的组合种数,那么:

\[dp[i][j]=\sum\limits_{k=1}^jdp[i-1][k] \]

这样就是\(\mathcal O(n^2m)\)的做法,不过容易发现\(dp[i][j]=dp[i][j-1]+dp[i-1][j]\)(我们这里把\(dp[i][0]\)初始化为\(0\)),这样就能做到\(\mathcal O(nm)\)了。

\(Code\)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MOD 1000000007 
int n,m;
int dp[25][1005];
int ans=0;
int main()
{
	#define read(x) scanf("%d",&x)
	read(n),read(m);
	m*=2;
	for(int i=1;i<=n;i++) dp[1][i]=1;
	for(int i=2;i<=m;i++)
	{
		for(int j=1;j<=n;j++) dp[i][j]=(dp[i][j-1]+dp[i-1][j])%MOD;
	}
	for(int i=1;i<=n;i++) ans=(ans+dp[m][i])%MOD;
	printf("%d\n",ans%MOD);
	return 0;
}
posted @ 2020-03-31 21:27  童话镇里的星河  阅读(181)  评论(0编辑  收藏  举报