hdu 6397 Character Encoding 2018杭电多校第八场-A (容斥)

题目链接

题意:

给定n, m, k;

本质上就是让你求下面这个不定方程的非负整数解的组数:

X1 + X2 + X3+...+ Xm = K, (0<=Xi<n)

首先不考虑Xi的最大取值限制,用隔板法;由于Xi可以为0,处理的时候k要加上m,转化为Xi最低为1。

然后由于Xi限制了最大数量为n,答案等于上面的结果减去不合要求的数量。计算当有i个X值超过n时的解的个数时,先单独拿出i个n,结果转化为 (k=(k-n*i)时的满足要求的解的个数)*C(m,i)。

但是,k=(k-n*i)时的满足要求的解的个数 还是不可求。我们能求的是当k=(k-n*i)时,没有Xi<=n这个限制的解的个数。例如,当i=1时,如果直接没有限制的答案的基础上减去(C(m+k-n*1-1,m-1)*C(m,1)) ,则多减去了i=2时的情况,所以要加回去,以此类推,所以:

即可转化为金典的容斥模型。即:

ans=C_{m+k-1}^{m-1}+\sum_{i=1}^{m}C_{m}^{i}*C_{m+k-i*n-1}^{m-1}*(-1)^{i}

 容斥原理

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=200010;
const int mod=998244353;
int T,n,m,k;
ll inv[M],fct[M];

ll Bpow(ll x,ll p){
    ll res=1;
    while(p){
        if(p&1)res=res*x%mod;
        p>>=1;x=x*x%mod;
    }
    return res;
}
void init(){
    inv[0]=fct[0]=1;
    for(int i=1;i<M;++i)fct[i]=fct[i-1]*i%mod;
    inv[M-1]=Bpow(fct[M-1],mod-2);
    for(int i=M-2;i>0;--i)inv[i]=inv[i+1]*(i+1)%mod;
}
ll C(int n,int m){
    if(n<0||m<0||n<m)return 0;
    if(m==0||n==m)return 1;
    return fct[n]*inv[m]%mod*inv[n-m]%mod;
}

int main(){
    scanf("%d",&T);
    init();
    while(T--){
        scanf("%d%d%d",&n,&m,&k);
        ll now=0,f=1;
        ll ans=0;
        while(k>=now*n){
            ans=(ans+mod+f*C(m,now)*C(k+m-1-now*n,m-1)%mod)%mod;
            f*=-1;
            now++;
        }
        printf("%lld\n",ans);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值