这题就是推递推关系,推了我两个小时,推出来以后觉得还是挺简单的。用一个二维数组存放结果,f(i, j)表示结果。除了当i = j时,f(i, i) = (i - 1) * [f(i - 1, i - 1) + f( i - 2, i - 2)]和j = 2时f(i,2) = f(i-1,2)+ i-1;之外,f(i, j)= f(i-1,j) + f(i-1,j -1)*(j - 1) + f(i - 1, j - 2) * (i - j + 1);原理很简单,就是在一般情况下,f(i, j)只会由f(i - 1, j)、f(i - 1, j - 1)、f(i-1, j-2)三项组成,因为当最后一个新郎加进原有的新郎里的时候,只会有这三种情况。代码如下:
/*
* hdu2049/linux.c
* Created on: 2011-7-25
* Author : ben
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void work();
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
work();
return 0;
}
unsigned long long ans[30][30];
void init() {
int i, j, k;
memset(ans, 0, sizeof(ans));
ans[2][2] = 1;
ans[3][3] = 2;
ans[3][2] = 3;
for (i = 4; i <= 20; i++) {
ans[i][i] = (i - 1) * (ans[i - 1][i - 1] + ans[i - 2][i - 2]);
for (j = i - 1; j > 2; j--) {
ans[i][j] = ans[i - 1][j];
ans[i][j] += ans[i - 1][j - 1] * (j - 1);
ans[i][j] += ans[i - 1][j - 2] * (i - j + 1);
}
ans[i][2] = ans[i - 1][2] + i - 1;
}
}
void work() {
int T, i, j;
init();
scanf("%d", &T);
while (T--) {
scanf("%d %d", &i, &j);
printf("%I64u\n", ans[i][j]);
}
}