好排列 题解
T<=10,0<=m<=n<=2000。
我们考虑这么思考,开始有长度为l-1的排列,现在我们在最后插入一个1~l的数,然后把数列中大于等于这个数的数全部加1,这样仍然是合法的。
这题想到这里就够了,我们就这样设计状态:dp[i][j]表示长度为i的排列按这种方法在最后插入了一个j,该加的加一之后的合法状态,就可以随便统计一下了。
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <string> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <sstream> #include <stack> #include <iomanip> #include <bitset> using namespace std; int T,n,m,ss[2333]; bool s[2333]; int dp[2003][2003]; int MOD=1000000007; void sol() { scanf("%d%d",&n,&m); memset(s,0,sizeof(s)); for(int i=1;i<=m;i++) scanf("%d",ss+i), s[ss[i]+1]=1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dp[i][j]=0; dp[1][1]=1; int ans=0; for(int i=2;i<=n;i++) { int sum=0; if(s[i]) { for(int j=1;j<=i;j++) { dp[i][j]=sum; sum=(sum+dp[i-1][j])%MOD; } } else { for(int j=i;j>=1;j--) { sum=(sum+dp[i-1][j])%MOD; dp[i][j]=sum; } } } for(int j=1;j<=n;j++) ans=(ans+dp[n][j])%MOD; printf("%d\n",ans); } int main() { freopen("good.in","r",stdin); freopen("good.out","w",stdout); scanf("%d",&T); while(T--) sol(); }