题目是莫涛神牛出的
题目描述
对于一个排列Ai,定义 F(A) = 满足Ai>i的i的个数,如F(2 3 1)=2。
Your Task
求F(A)=M的1..N的排列的个数。
输入文件
一行两个整数 N M。
输出文件
一行包含一个整数表示所求数目对 10^9+7 取模的结果。
样例输入
3 1
样例输出
4
样例解释
满足要求的 4 个排列是:(1 3 2) (3 1 2) (3 2 1) (2 1 3)。
数据约定
30%:N<=20
100%:0<=M<N<=2000
我觉得还是挺容易想的,毕竟我一个小时就想出来,然后就去刷noip包了
题解:
F[i][j]表示1..i的F(A)=j的排列的个数。
F[i][0] = 1
F[i][j] = f[i - 1][j] * (j + 1) + F[i - 1][j - 1] * (i - j)
思考方法:先将i放在第i位,然后与前面i-1个数中的某个进行交换。
然后是我的code
#include <cstdio>
#include <iostream>
using namespace std;
const int mo = 2;
const int MO = (int)1e9 + 7;
const int maxn = 2 + 5;
const int maxm = 100000 + 5;
int n, m;
long long f[maxn][maxm];
int main()
{
freopen("pailie.in", "r", stdin);
freopen("pailie.out", "w", stdout);
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
f[i % mo][0] = 1;
for (int j = 1; j <= i; ++j)
{
f[i % mo][j] = f[(i - 1) % mo][j] * (j + 1) + f[(i - 1) % mo][j - 1] * (i - j);
f[i % mo][j] %= MO;
//1.替换了j次, 增加了1次
//2.保证稳增加1个, 反向取补集
}
}
cout << f[n % mo][m] % MO << endl;
return 0;
}
再有mt的code
#include <iostream>
using namespace std;
const int maxn = 2005, mo = int(1e9) + 7;
long long f[maxn][maxn];
int n, m;
int main()
{
freopen("pailie.in", "r", stdin);
freopen("pailie.out", "w", stdout);
cin >> n >> m;
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
f[i][0] = 1;
for (int j = 1; j < i; ++j)
f[i][j] = (f[i - 1][j] * (j + 1) + f[i - 1][j - 1] * (i - j)) % mo;
}
cout << f[n][m] << endl;
return 0;
}