HDU6397

时间:2021-12-22 16:11:31

HDU6397
用小于n的m个数组成k,求方案数mod 998244353
如果没有n的限制,直接用隔板法求就可以
因为m个数中可以为0,所以不妨先都放上一个1,转化成不能为0的m个数来凑k+m,即C(k+m-1,m-1);
加了限制之后就用容斥原理去维护就好了
至少有i个不小于n的方案数为C(m,i)*C(k+m-1-i*n,m-1);
total-至少有一个不小于n+至少有2个不小于n的...

一定要小心阶乘的初始化啊,f[0]=1;

哭了

 #include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<set>
#include<map>
#include<stack>
#include<cstring>
#define inf 2147483647
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,nl,mid,l,r
#define rson rs,mid+1,nr,l,r
#define N 100010
#define mod 998244353
#define For(i,a,b) for(long long i=a;i<=b;i++)
#define p(a) putchar(a)
#define g() getchar() using namespace std;
long long T;
long long n,m,k;
long long f[],In[],fin[];
long long ans;
void in(long long &x){
long long y=;
char c=g();x=;
while(c<''||c>''){
if(c=='-')y=-;
c=g();
}
while(c<=''&&c>=''){
x=(x<<)+(x<<)+c-'';c=g();
}
x*=y;
}
void o(long long x){
if(x<){
p('-');
x=-x;
}
if(x>)o(x/);
p(x%+'');
} void pre(){
f[]=In[]=fin[]=;
f[]=;
fin[]=;
For(i,,){
In[i]=(mod-mod/i)*In[mod%i]%mod;
fin[i]=fin[i-]*In[i]%mod;
f[i]=f[i-]*i%mod;
}
} long long C(long long x,long long y){
if(y>x) return ;
return f[x]*fin[y]%mod*fin[x-y]%mod;
} int main(){
in(T);
pre();
while(T--){
in(n);in(m);in(k);
ans=C(k+m-,m-);
for(int i=;i<=m;i++){
long long res=C(m,i)*C(k+m--i*n,m-)%mod;
if(i%==)
ans=(ans+mod-res)%mod;
else
ans=(ans+res)%mod;
}
o(ans);p('\n');
}
return ;
}

相关文章