Miscellaneous [Title] [LibreOJ # 6608] unconscious heap of stones inclusion and exclusion [] [FFT]

Description

Here Insert Picture Description

Solution

943718401=225*2^22+1

Obviously there must be two per row, we might have enumeration k lists two stones, then there are 2 (nk) lists a stone.
\ [Ans = \ sum \ limits_ {k = 0} ^ {n} {m \ choose k} {mk \ choose 2 (nk)} S_k \]

Abstract about the problem, we have n colors of balls, each color of the ball and there is no difference between the two, they now want to put k + 2 (nk) a differentiated box, where k boxes disorder put two balls, 2 (nk) a box to put a ball, the same color of the ball can not be placed in the same box, \ (S_k \) is the number of the program, we only need to quickly calculate all the \ (S_k \) .

The same color of the ball can not be placed in the same box to limit the more annoying, we consider the inclusion and exclusion.
Enumerate how many boxes to put two balls of the same color.

N i-th color selected from colors, k i boxes selected boxes, placed in a certain order.
Let's assume that two different balls of the same color, k ordered a box of two balls, and finally removed.
The remaining (2n-2i)! Balls and then to fill a box in a certain order.

那么有
\[S_k={1\over 2^{n+k}}\sum\limits_{i=0}^{k}{k\choose i}{n\choose i}i!(-1)^{i}2^i(2n-2i)!\]

This is in the form of a convolution, FFT can be accelerated.

This convolution only once, even if the answers.
Time complexity \ (O (n \ log n ) \)

Code

#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define LL long long
using namespace std;
int M,L;
const int mo=943718401;
const int MAXM=4194304;
LL js[MAXM+1],ny[MAXM+1];
LL ksm(LL k,LL n)
{
    LL s=1;
    for(;n;n>>=1,k=k*k%mo) if(n&1) s=s*k%mo;
    return s;
}
namespace poly
{   
    int wi[MAXM+1],bit[MAXM+1],ns;
    void init()
    {
        js[0]=1;
        fo(i,1,M) js[i]=js[i-1]*i%mo,bit[i]=(bit[i>>1]>>1)|((i&1)<<(L-1));
        ny[M]=ksm(js[M],mo-2);
        fod(i,M-1,0) ny[i]=ny[i+1]*(i+1)%mo;
        wi[0]=1;
        wi[1]=ksm(7,(mo-1)/M);
        
        fo(i,2,M) wi[i]=(LL)wi[i-1]*wi[1]%mo;
        ns=ksm(M,mo-2);
    }
    void DFT(int *a)
    {
        int v;
        fo(i,0,M-1) if(i<bit[i]) swap(a[i],a[bit[i]]);
        for(int h=1;h<M;h<<=1)  
        {
            int wn=wi[M/h/2];
            for(int j=0;j<M;j+=h*2)
            {
                int *x=a+j,*y=x+h,w=1;
                for(int i=0;i<h;i++,x++,y++,w=(LL)w*wn%mo)
                {   
                    v=(LL)*y * w%mo;
                    *y=(*x-v+mo)%mo;
                    *x=(*x+v)%mo;
                }
            }
        }
    }
    void IDFT(int *a)
    {
        DFT(a);
        fo(i,0,M-1) a[i]=(LL)a[i]*ns%mo;
        reverse(a+1,a+M);
    }
}
using poly::init;
using poly::DFT;
using poly::IDFT;
LL n,m;
LL C(int n,int m)
{
    if(n<m) return 0;
    return js[n]*ny[m]%mo*ny[n-m]%mo;
}
int a[MAXM+1],b[MAXM+1];
int main()
{   
    cin>>n>>m;
    M=1,L=0;
    while(M<2*n+2) M<<=1,L++;
    init();
    LL v=1;
    fo(i,0,n)
    {
        a[i]=v*C(n,i)%mo*js[2*(n-i)]%mo%mo;
        b[i]=ny[i]%mo;
        v=mo-v;
        v=v*2%mo;
    }
    DFT(a),DFT(b);
    fo(i,0,M-1) a[i]=(LL)a[i]*b[i]%mo;
    IDFT(a);
    LL ans=0,vs=1,ck=1,cn=1;
    fo(i,0,min(m-1,n*2-1)) cn=(m-i)%mo*js[i]%mo*ny[i+1]%mo*cn%mo;
    fo(i,0,n)
    {
        if(2*(n-i)<=m-i) ans=(ans+vs*ck%mo*cn%mo*a[i]%mo*js[i]%mo)%mo;
        vs=vs*ny[2]%mo;
        ck=(m-i)%mo*js[i]%mo*ny[i+1]%mo*ck%mo;
        if(2*(n-i)<=m-i) cn=cn*ksm((m-i)%mo*((m-2*n+i+1)%mo)%mo,mo-2)%mo*(((n-i)*2-1+mo)%mo*((n-i)*2%mo)%mo)%mo;
    }
    ans=ans*vs%mo*2%mo;
    printf("%lld\n",ans);
}

Guess you like

Origin www.cnblogs.com/BAJimH/p/11001631.html