hdu 多校容斥

 从0-(n-1)选m个数和为k的方案数

设f[i]为有i个位置大于n的方案

f[0]=all-(f[1]∪f[2]∪f[3]。。)

=all-f[1]-f[2]..+(f[1]∩f[2])。。。

奇减偶加

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const ll maxn=1e6+5;

ll A[5*maxn],FA[5*maxn];
ll qpow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
void init()
{
    ll i;
    A[0]=1;
    FA[0]=1;
    for(i=1; i<=3*maxn; i++)
        A[i]=A[i-1]*i%mod;
        FA[2*maxn]=qpow(A[2*maxn],mod-2);
        for(i=2*maxn;i>1;i--)
            FA[i-1]=FA[i]*i%mod;
}
ll cp(ll n,ll m)
{
    if(m>n)
        return 0;
    return A[n]*FA[n-m]%mod*FA[m]%mod;
}
int main()
{
    ll i,j,k,n,m,t;
    ll num,sum,ans,p;
    init();
    scanf("%I64d",&t);
    while(t--)
    {
       scanf("%I64d%I64d%I64d",&n,&m,&k);
       ans=cp(k+m-1,m-1);
       for(i=1;i<=(k/n);i++)
       {
           if(i&1)
            ans-=(cp(m,i)*cp(k-i*n+m-1,m-1)%mod);
           else
            ans+=(cp(m,i)*cp(k-i*n+m-1,m-1)%mod);
            ans=(ans+mod)%mod;
       }
       ans=ans%mod+mod;
       printf("%I64d\n",ans%mod);
    }
    return 0;
}

 

posted @ 2018-08-15 21:25  电竞毒奶  阅读(146)  评论(0编辑  收藏  举报