Codeforces 403D: Beautiful Pairs of Numbers(DP)

题意:转换模型之后,就是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;
}

 

原文地址:https://www.cnblogs.com/shinecheng/p/3608586.html