题目的大意是指,给出n长度的数列,其实1的连续个数不超过a,2的连续个数不超过b。
我一开始想到的是排列组合的规律题,尝试了好久都是一直Wrong Answer,后来受到队友的启(ti)发(shi),试着用dp来做。
嗯~纠结了挺久的,边界条件还写错了。一开始直接用递归来做,结果超时了。超时的具体原因是因为数据比较大,会爆栈空间(Window下),估计测评环境是Linux,所以是超时而不是Runtime Error。
于是就把递归改成递推,结果还是超时。发现是把循环结束条件写到了if语句中的判断了,从理论上说是没什么区别的,但是放在里面是超时,放在外面要修改边界条件(PS:判断语句放在里面的话是and关系会计算错误,放在外面才可以,可能是编译优化的问题吧),改了之后就AC啦。
(真是坎坷曲折啊,充分体现了我的dp是存在挺大问题的)
#include <iostream>
#include <algorithm>
const int MO = 1e9+7;
using namespace std;
int a, b, dp[3][50005];//dp[i][j]是指长度为j,以i结尾的序列的种数,它是由后面小于等于a/b长度均为1/2的序列的种数累加而成的
int main()
{
int n, i, j;
cin >> n >> a >> b;
dp[1][0] = dp[2][0] = 1;
for (i = 1; i <= n; ++ i)
{
for (j = 1; j <= a; ++ j) if (i-j>=0) dp[1][i] = (dp[1][i] + dp[2][i-j]) % MO;//i-j==0意味着最后的a个都是1,也是合法的序列
for (j = 1; j <= b; ++ j) if (i-j>=0) dp[2][i] = (dp[2][i] + dp[1][i-j]) % MO;
}
cout << (dp[1][n] + dp[2][n]) % MO << endl;
return 0;
}