Codeforces 932E Team Work 数学

Team Work

发现网上没有我这种写法。。

i ^ k我们可以理解为对于每个子集我们k个for套在一起数有多少个。

那么我们问题就变成了 任意可重复位置的k个物品属于多少个子集。

然后我们枚举k个物品所占位置的个数 i , 然后需要计算有多少种方案能把k个不同物品放入i个桶中。

这个东西可以用dp[ i ][ j ] 表示 i 个物品放入 j 个桶中的方案数。 dp[ i ][ j ] = dp[ i - 1 ][ j ] * j + dp[ i - 1 ][ j - 1 ] * j

然后就可以求答案啦。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long
using namespace std;

const int N = 5000 + 7;
const int M = 2e6 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;

LL n, k;

LL power(LL a, LL b) {
    LL ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod; b >>= 1;
    }
    return ans;
}

LL comb(int n, int m) {
    if(n < 0 || n < m) return 0;
    LL A = 1, B = 1;
    for(int i = 0; i < m; i++)
        A = A * (n - i) % mod, B = B * (i + 1) % mod;
    return A * power(B, mod - 2) % mod;
}


LL dp[N][N];
int main() {
    for(int i = 1; i < N; i++) {
        for(int j = 1; j <= i; j++) {
            if(j == 1) dp[i][j] = 1;
            else dp[i][j] = (dp[i-1][j] * j % mod + dp[i-1][j-1] * j % mod) % mod;
        }
    }
    scanf("%lld%lld", &n, &k);
    LL ans = 0;
    for(int i = 1; i <= min(n, k); i++) {
        LL ret = comb(n, i);
        ret = ret * power(2, n - i) % mod * dp[k][i] % mod;
        ans = (ans + ret) % mod;
    }
    printf("%lld\n", ans);
    return 0;
}

/*
*/

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/10404362.html