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
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;i0;--i)inv[i]=inv[i+1]*(i+1)%mod;
}
ll C(int n,int m){
    if(n<0||m<0||n=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);
    }
}

 

你可能感兴趣的:(#,数论,ACM)