【SDOI】【DP】【滚动数组】【bzoj1925】地精部落
1925: [Sdoi2010]地精部落
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 814 Solved: 494
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
HINT
对于 20%的数据,满足 N≤10;
对于 40%的数据,满足 N≤18;
对于 70%的数据,满足 N≤550;
对于 100%的数据,满足 3≤N≤4200,P≤109
Source
这个题真是神了。。。代码量和思维量是完全成反比的。。。
思路:比较复杂。首先抽象出模型,是求一个长度为n的抖动序列的方案数。令f[i][j]表示以j开头长度为i的,且开始是下降的方案数,答案就是乘2(考虑开始是上升的方案数),然后进行更深一步的思考:
<1>考虑开始的数是j-1,它的方案数就是f[i][j-1]。
<2>考虑开始的数是j,因为我们求的是开始下降,所以它的第二位一定要小于它,即j-1,但这样以j-1开始的序列就变成了上升的,所以要把它翻转过来,这样j-1就变成了(i-1)-(j-1)+1=i-j+1。
所以dp方程就是f[i][j]=f[i][j-1]+f[i][i-j+1] (1<=j<=i),初始化时f[2][2]=1。需要用到滚动数组(重复利用的原则),不然就MLE了。
Code:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int n,p,x,f[2][5001]; int main(){ scanf("%d%d",&n,&p); f[0][2]=1; for (int i=3; i<=n+1; i++){ x=i&1; for (int j=1; j<=i; j++) f[x][j]=(f[x][j-1]+f[!x][i-j+1])%p; } printf("%d\n",(f[x][n]*2)%p); return 0; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。