4555 bzoj

题意:求$ \ sum_ {i = 0} ^ {n}は\ sum_ {J = 0} ^ {I} S(i、j)は2 ^ {J} J $!

実行することはできません見て...

しかし、まだの慎重な分析が必要

最も重要なステップは、変換です。

クラスの数は、第二スターリング定義されます。$ S(n、m)は$プログラムは$のN-Mに$ $ $異なる物品をセット表します

そして、その合計の内側に物事を考え、意味がセットに異なる$ $ I $ J $の記事を発見され、各セットは、属性の2種類があり、その後、これらのプログラムのセット全体が配置されている番号

したがって、この定義に基づいて、リセット状態の$ G(N)= \ sum_ {J = 0} ^ {I} S(i、j)は2 ^ {J} jは$、そこ再帰式:! $ G(N) = \ sum_ {J = 1} ^ {n}は2C_ {N} ^ {I} G(NI)$

この再帰的な列挙は、得られた素子の第1セットの起源であります

与えるために、組み合わせの数を拡大するルーチンよります

$ G(N)= \ sum_ {i = 1} ^ {n}は2 \ FRAC {N!} {I!(NI)!} G(NI)$

移調を得ることができます。

$ \ FRAC {G(N)} {N!} = \ sum_ {i = 1} ^ {N} \ FRAC {2} {I!} \ FRAC {G(NI)} {(NI)!} $

だから、右は明らかに畳み込みの形であります

设$ F(X)= \ sum_ {i = 1} ^ {N} \ FRAC {2} {I!} X ^ {I} $

$ G(X)= \ sum_ {i = 0} ^ {N} \ FRAC {G(I)} {(I)!} X ^ {I} $

この場合に直接コンボリューションの$ G(0)= 0 $を指摘、それは$ G(0)= 1 $(境界要件)が必要

したがって、それは決定することができる$ G(X)= F(x)をG(x)+ 1 $

転置得る$ G(X)= \ FRAC {1} {1-F(X)} $

(この方法は、湿分硬化のように使用することができ、FFT前記)

など、$ Gを得るために、(x)の使用は何$?

$ Iは、それぞれが!$ $のG(X)$生成機能を入手し、直接合算することができます$ $ G(x)のために、参照してください。

コードを貼り付けます。

書式#include <cstdioを> 
する#include <cmath> 
の#include <CStringの> 
の#include <cstdlib> 
書式#include <iostreamの> 
の#include <アルゴリズム> 
書式#include <キュー> 
の#include <スタック>
 に#define LL長い長い
 使って 名前空間はstd;
constの LLモード= 998244353 ; 
LL F [ 100005 ]。
LL FF [ 100005 ]。
G LL [ 100005 ]。
LLのINV [ 100005 ]。
[MUL LL 100005 ]。
LLのMINV [ 100005 ]。
INT [(に1 << 20)+ 5 ]。
int型のn;
無効INITを()
{ 
    INV [ 0 ] = INVを[ 1 ] = MUL [ 0 ] = MUL [ 1 ] = MINV [ 0 ] = MINV [ 1 ] = 1 以下のためにint型 I = 2 ; iは= < 100000 ; iは++ 
    { 
        INV [I] =(モードモード/ i)は* INV [モード%I]%のモード。
        MINV [I] = MINV [I- 1 ] * INV [I]%のモード。
        MUL [I] = MUL [I-1 ] * I%のモード。
    } 
} 
のLL pow_mul(LLのX、LLのY)
{ 
    LL RET = 1 一方、(Y)
    { 
        場合(Y&1)RET = RET * X%のモード。
        X = X * X%のモード、Y >> = 1 
    } 
    戻りRET。
} 
ボイド NTT(LL *、INT LEN、INT K)
{ 
    ためint型 I = 0を私は++; iがLEN <)であれば(私は< スワップ([I]、[I]乃至[I]に) ]);
    以下のためのint型私は=1 ; iがLEN <; I << = 1 
    { 
        LL W0 = pow_mul(3、(モード- 1)/(I << 1 ))。
        INT J = 0 ; J <LEN; J + =(I << 1 ))
        { 
            W LL = 1 INT O = 0 ; 0 <私は、O ++、W = W * W0%のモード)
            { 
                LL W1 = A [J + O]、W2 = [J + O + I] * W。
                [J + O] =(W1 + W2)%のモード、[J + O + I] =((W1-W2)%モード+モード)%のモード。
            }
        } 
    } 
    もし(K == - 1 
    { 
        LL INV = pow_mul(LEN、モード- 2 )。
        以下のためにint型 i = 1 ; iが<(LEN >> 1); iは++)スワップ([I]、[len- I])。
        以下のためにint型 iは= 0 ; iがLEN <; I ++)は、[I] [I] * INV%の= モード。
    } 
} 
LL [(1 << 20)+ 5 ]、B [(1 << 20)+ 5 ]、C [(1 << 20)+ 5 ]。
空隙get_inv(LLの* fとのLL * gを、INT DEP)
{ 
    場合(DEP == 1 
    { 
        G [ 0 ] = pow_mul(F [ 0 ]、モード- 2 )。
        返します
    } 
    INT NXT =(DEP + 1)>> 1 
    get_inv(F、G、NXT)。
    INT LIM = 1、L = 0 一方、(LIM <= 2 * DEP)LIM << = 1、L ++ 以下のためにint型 i = 0 ; iは<LIM; iは++)への[I] =((の[I >> 1 ] >> 1)|((I&1)<<(1- 1 )));
    以下のためにint型 i = 0 ; I <LIM; iは++)A [I] = B [I] = 0 ;
    以下のためにint型 i = 0 ; iはDEP <; iは++)A [i]は= Fの[I]。
    以下のためにint型 i = 0 ; iはNXTを<; iは++)B [I] = G [i]は、
    NTT(A、LIM、1)、NTT(B、LIM、1 )。
    以下のためにint型 i = 0 ; I <LIM; iは++)C [I] = A [I] * B [i]は%モード* B [I]%のモード。
    NTT(C、LIM、 - 1 )。
    にとってint型 i = 0 ; iはDEPを<; I ++の)グラム[I] =((2 * gの[I] -C [I])%モード+モード)%のモード。
} 
int型のmain()
{ 
    scanf関数(" %のD "、&N)
    その中に(); 
    N ++ ;
    以下のためにint型 i = 1 ; iがn <; iは++)F [I] =( - 2LL * MINV [I]%モード+モード)%のモード。
    F [ 0 ] = 1 
    get_inv(F、FF、N)。
    LL S = 0 int型 iは= 0、S =(S + FF [I] * MUL [I]%モード)%; iがN <I ++は)モード; 
    printf(" %LLDする\ n " 、S);
    リターン 0 ; 
}

 

おすすめ

転載: www.cnblogs.com/zhangleo/p/11016660.html