Codeforces 960G Bandit Blues 第一类斯特林数+分治FFT

懒人模式:orz beginend
code:

#include
#include
#include
#include
#include
#define LL long long
using namespace std;
const LL p=998244353,yg=3;
LL A[400010];
LL bin[400010];
LL pow(LL a,LL b)
{
    LL ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%p;
        a=a*a%p;b>>=1;
    }
    return ans;
}
void ntt(LL *a,LL n,LL op)
{
    for(LL i=0;i>1]>>1)|((i&1)*(n>>1));
    for(LL i=0;iif(ifor(LL i=1;i1)
    {
        LL wn=pow(yg,op==1?(p-1)/(2*i):(p-1)-(p-1)/(2*i)),w,t;
        for(LL j=0;j1)
        {
            w=1;
            for(LL k=0;kif(op==-1)
    {
        LL Inv=pow(n,p-2);
        for(LL i=0;ivoid solve(LL *a,LL len,LL l,LL r)
{
    if(l==r) {a[0]=l;a[1]=1;return;}
    LL mid=(l+r)/2;LL a1[len],a2[len];
    memset(a1,0,sizeof(a1));memset(a2,0,sizeof(a2));
    solve(a1,len>>1,l,mid);solve(a2,len>>1,mid+1,r);
    ntt(a1,len,1);ntt(a2,len,1);
    for(LL i=0;i1);
}
LL C(LL m,LL n)
{
    LL fac1=1,fac2=1;
    for(LL i=1;i<=n;i++) (fac1*=i)%=p,(fac2*=(m-i+1))%=p;
    return fac2*pow(fac1,p-2)%p;
}
int main()
{
    scanf("%lld %lld %lld",&n,&a,&b);
    if(a+b-2>n-1||!a||!b) return puts("0"),0;
    if(n==1) return puts("1"),0;
    LL N=n-1,M=a+b-2;
    LL len=1;while(len<(n+1)<<1) len<<=1;
    solve(A,len,0,N-1);
    printf("%lld",A[M]*C(a+b-2,a-1)%p);
}

你可能感兴趣的:(斯特林数,NTT,分治,组合数学,dp)