hdu6397 Character Encoding 母函数解约束条件下多重集

 

http://acm.hdu.edu.cn/showproblem.php?pid=6397

原问题的本质是问m个元素的多重集S,每一种类型的对象至多出现n-1次的S的k组合的个数是多少?

等价于 x1+x2+...+xm=k  0<xi<=n-1  的解的个数

当xi没有上限(xi<=n-1)时由隔板法得C(k+m-1,m-1)

而有上限时,方法是构造母函数(1+x+....+x^(n-1))^m  答案是x^k的系数

对母函数用等比数列求和再二项式展开加泰勒展开得答案。orz(解法来自知乎,侵删)

#define _CRT_SECURE_NO_WARNINGS
#include<cmath>
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const int maxn = 5e5 + 10;
const ll mod = 998244353;


int n, m, k;



ll inv[maxn], f[maxn], fac[maxn];
ll c[maxn];
long long kpow(long long a, long long n) {
    long long res = 1;
    while (n > 0) {
        if (n & 1)res = res * a%mod;
        a = a * a%mod;
        n >>= 1;
    }
    return res;
}
void init() {
    f[0] = 1; f[1] = 2;
    fac[0] = fac[1] = 1;
    inv[1] = 1;
    rep(i, 2, maxn) {
        fac[i] = fac[i - 1] * (ll)i % mod;
        inv[i] = kpow(fac[i], mod - 2);
    }
}
ll C(int n, int m) {
    if (n < m) return 0ll;
    if (m == 0 || n == m) return 1ll;
    if (n - 1 == m || m == 1) return n;
    return fac[n] * inv[m] % mod * inv[n - m] % mod;
}

int main() {
    int t;
    cin >> t;
    init();
    while (t--) {
        cin >> n >> m >> k;
        mmm(c, 0);
        ll fl = 1;
        ll ans = 0;
        rep(r, 0, k / n) {
            ans += fl * C(m, r)*C(m + k - n * r - 1, k - n * r) % mod; fl = -fl;
            if (ans < 0)ans += mod;
            ans %= mod;
        }
        cout << ans  << endl;
    }

}

 

posted @ 2018-08-15 20:01  SuuTTT  阅读(307)  评论(0编辑  收藏  举报