p2401
不等数列
题目描述
将 \(1\) 到 \(n\) 任意排列,然后在排列的每两个数之间根据他们的大小关系插入> 和 <。问在所有排列中,有多少个排列恰好有 \(k\) 个 <。答案对 \(2015\) 取模。
注:\(1 \sim n\) 的排列指的是 \(1 \sim n\) 这 \(n\) 个数各出现且仅出现一次的数列。
输入格式
一行两个整数,表示 \(n\) 和 \(k\)。
输出格式
一个整数表示答案。
样例 #1
样例输入 #1
5 2
样例输出 #1
66
提示
对于 \(30\%\) 的数据,\(n\leq 10\);
对于 \(100\%\) 的数据,\(0\leq k<n\leq 1000\)。
很好的一道DP题
f[i][j] 1~i j个'<'的方案数
考虑1~i+1
由于1~i一共有i-1个不等号 j个< 则 i-1-j个>
当 i+1 插入 < 则不改变<的个数
i+1插入 > 则小于号的个数+1
i+1插入最左边 小于号不变
i+1插入最右边 小于号+1
就可以推出状态转移方程了
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,k,f[1005][1005];
const int mod=2015;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
f[1][0]=1;
for(int i=2;i<=n;i++)
for(int j=0;j<=i;j++)
{
f[i][j]=(f[i][j]+(j+1)*f[i-1][j])%mod;
f[i][j+1]=(f[i][j+1]+(i-1-j)*f[i-1][j])%mod;
}
cout<<f[n][k]<<"\n";
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号