解题报告: 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_1leqslant a_2leqslant ......leqslant a_nleqslant b_nleqslant b_{n-1}leqslant b_1 ]

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

[dp[i][j]=sumlimits_{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
",ans%MOD);
	return 0;
}
原文地址:https://www.cnblogs.com/tlx-blog/p/12608665.html