考虑DP。
如果把转移看出当前位填什么数的话,这样是有后效性的。
如果考虑当前的序列是将1至n依次插入序列中的话。
考虑将i插入1到i-1的序列中,如果插入到<号中或者首部,那么最后就会多出一个大于号。
如果插入到>号中或者尾部,那么最后就会多出一个小于号。
所以定义状态dp[i][j]表示1到i组成的序列中,小于号的数目为j的方法数。转移方程即为所求。
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi 3.1415926535 # define eps 1e-9 # define MOD 100000007 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; int Scan() { int res=0, flag=0; char ch; if((ch=getchar())==‘-‘) flag=1; else if(ch>=‘0‘&&ch<=‘9‘) res=ch-‘0‘; while((ch=getchar())>=‘0‘&&ch<=‘9‘) res=res*10+(ch-‘0‘); return flag?-res:res; } void Out(int a) { if(a<0) {putchar(‘-‘); a=-a;} if(a>=10) Out(a/10); putchar(a%10+‘0‘); } const int N=1005; //Code begin... int dp[N][N]; int dfs(int x, int y){ if (~dp[x][y]) return dp[x][y]; if (y==0||y==x-1) return dp[x][y]=1; if (y>=x) return 0; int ans=(dfs(x-1,y)*(y+1)%2012+dfs(x-1,y-1)*(x-y)%2012)%2012; return dp[x][y]=ans; } int main () { int n, k; mem(dp,-1); scanf("%d%d",&n,&k); printf("%d\n",dfs(n,k)); return 0; }
时间: 2024-10-10 19:58:32