hdu3664(递推dp)

时间:2023-03-08 16:10:19
hdu3664(递推dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3664

分析:dp[i][j]表示i个数的排列中E值为j的个数。假设现在已有一个E值为j的i的排列,对于新加入的一个数i+1,将其加入排列的方法有三:

1)把它放最后,加入后E值不变

2)把它和一个满足A[k]>k的数交换,A[k]到最后,A[k]必定小于i+1,交换后E值不变,符合这样的k共有j个

3)把它和一个不满足A[k]>k的数交换,A[k]到最后,A[k]必定小于i+1,交换后E值+1,符合这样的k共有i-j个

根据这三种方法得到转移方程dp[i][j] = dp[i - 1][j] + dp[i - 1][j] * j + dp[i - 1][j - 1] * (i - j);

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define inf 1<<30
#define mod 1000000007
using namespace std;
LL f[][];
void init()
{
for (int i=;i<=;i++)
{
f[i][]=;
for (int j=;j<i;j++) f[i][j]=((j+)*f[i-][j]+(i-j)*f[i-][j-])%mod;
}
} int main()
{
int n,k;
init();
while (scanf("%d%d",&n,&k)>) printf("%I64d\n",f[n][k]);
return ;
}