题意:转换模型之后,就是1~n个数中选k个,放到一个容量为n的背包中,这个背包还特别神奇,相同的物品摆放的位置不同时,算不同的放法(想象背包空间就是一个长度为n的数组,然后容量为1的物体放一个格子,容量为n的物体放在相邻的n个格子里。问方案数。
方法:
选k个物品放在背包中有多少种放法。
然后就是k个物品放了以后,还剩下几个空位,空位的位置不同,则方案数也不同。所以要求出几个空位放在几个地方有多少方案数
最后相乘,再乘上阶乘就好了。
#include <cstdio> #include <cstring> #include <cstdlib> #define mod 1000000007 long long dp[1010][55]; int ans[1010][55]; //ans[v][ long long jie[55]; long long f[1010][55]; void init() { memset(dp, 0, sizeof(dp)); dp[0][0] = 1; for (int now = 1; now <= 1000; now++) { for (int v = 1000; v-now >= 0; v--) { for (int k = 50; k >= 1; k--) { dp[v][k] = dp[v-now][k-1] + dp[v][k]; dp[v][k] %= mod; } } } for (int i = 0; i <= 1000; i++) { f[i][1] = 1; } for (int h = 2; h <= 50; h++) { for (int q = 0; q <= 1000; q++) { f[q][h] = 0; for (int j = 0; j <= q; j++) { f[q][h] += f[q-j][h-1]; f[q][h] %= mod; } } } for (int v = 1; v <= 1000; v++) { for (int k = 1; k <= 50; k++) { ans[v][k] = 0; for (int j = 1; v-j >= 0; j++) { ans[v][k] = (ans[v][k] + (dp[j][k]*f[v-j][k+1])%mod)%mod; } } } jie[1] = 1; for (int k = 2; k <= 50; k++) { jie[k] = (jie[k-1] * k)%mod; } } int main() { init(); int t; scanf("%d", &t); while (t--) { int n, k; scanf("%d%d", &n, &k); if (k > 50) { printf("0 "); continue; } printf("%d ", (int)((jie[k]*ans[n][k])%mod)); } return 0; }