题目链接: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;
}