hdu 6397 Character Encoding 组合数+容斥

版权声明:本文为博主原创文章,转载请附上原博客链接。 https://blog.csdn.net/Dale_zero/article/details/82121132

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6397

结论1:m个大于等于0的数字组成k有C(m+k-1,m-1)种方案

当有x人的取值>=n时,原式x1+x2+..xm=k,将每个大于n的数减n,就变成了x1+x2+...+xn=k-x*n,就可以用结论1求解了。

容斥求解奇数就取减号,偶数取加号。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod  998244353
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;

const int maxn=200010;
LL mx;
LL fac[maxn], inv[maxn];
int powi(LL a,LL b)
{
    int c = 1;
    for (; b; b >>= 1, a = 1ll * a * a % mod)
        if (b & 1) c = 1ll * c * a % mod;
    return c;
}

LL C(LL a, LL b)///a>b
{
    if(a==b) return 1;
    else if(a<b) return 0;
    return 1ll * fac[a] * inv[b] % mod * inv[a - b] % mod;
}
///初始化
void init()
{
    mx = maxn-1;///开的数组大小
    fac[0] = 1; for (int i = 1; i <= mx; ++ i) fac[i] = 1ll * fac[i - 1] * i % mod;
    inv[mx] = powi(fac[mx], mod - 2); for (int i = mx - 1; ~i; -- i) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
}


int main()
{
    int t;
    scanf("%d",&t);
    init();
    while(t--)
    {
        LL n,m,k;
        scanf("%lld%lld%lld",&n,&m,&k);
        LL ans=C(m+k-1,m-1);
        for(int i=1;n*i<=k;i++)
        {
            if(i&1)
                ans=(ans+mod-(C(m+k-1-i*n,m-1)*C(m,i))%mod)%mod;
            else
                ans=(ans+(C(m+k-1-i*n,m-1)*C(m,i)))%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dale_zero/article/details/82121132
今日推荐