dp.
用f[i][j]表示长度为i,开头数为[1,j]的第一位下降的序列个数。
f[i][j]=f[i][j-1]+f[i-1][i-j]。
f[i-1][i-j]可以表示长度为i-1,开头数为[1,j-1]的第一位上升的序列个数。(各位取反以后,俩者一一对应,所以值相同)
要使用滚动数组。
好像%2和&1性能上没差别。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 5000 + 10; int n,p,x,y; int f[2][maxn]; int main() { scanf("%d%d",&n,&p); f[1][1]=1; for(int i=2;i<=n;i++) { x=i&1; y=x^1; for(int j=1;j<=i;j++) f[x][j]=(f[x][j-1]+f[y][i-j])%p; } printf("%d ",n==1?1%p:f[n&1][n]*2%p); return 0; }