• [Luogu5162]WD与积木(多项式求逆)


    不要以为用上Stirling数就一定离正解更近,FFT都是从DP式本身出发的。

    设f[i]为i个积木的所有方案的层数总和,g[i]为i个积木的方案数,则答案为$frac{f[i]}{g[i]}$

    转移枚举第一层是哪些积木:$$f_n=g_n+sum_{i=1}^{n}inom{n}{i}f_{n-i},f_0=0$$$$g_n=sum_{i=1}^{n}inom{n}{i}g_{n-i},g_0=1$$

    转化成卷积形式:$$frac{f_n}{n!}=frac{g_n}{n!}+sum_{i=1}^{n}frac{1}{i!} imes frac{f_{n-i}}{i!}$$$$frac{g_n}{n!}=sum_{i=1}^{n}frac{1}{i!} imes frac{g_{n-i}}{(n-i)!}$$

    构造生成函数:$F(x)=sumfrac{f_i}{i!}x^i$,$G(x)=sumfrac{g_i}{i!}x^i$,$H(x)=sumfrac{x^i}{i!}$。

    则根据上式有:$F(x)=G(x)+F(x)(H(x)-1)-1$,$G(x)=G(x)(H(x)-1)+1$。

    移项得:$F(x)=frac{G(x)-1}{2-H(x)}=G(x)(G(x)-1)$,$G(x)=frac{1}{2-H(x)}$。

    多项式求逆即可。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     4 using namespace std;
     5 
     6 const int N=500010,mod=998244353;
     7 int n,m,T,fac[N],h[N],g[N],f[N],inv[N],rev[N],tmp[N];
     8 
     9 int ksm(int a,int b){
    10     int res=1;
    11     for (; b; a=1ll*a*a%mod,b>>=1)
    12         if (b & 1) res=1ll*res*a%mod;
    13     return res;
    14 }
    15 
    16 void DFT(int a[],int n,bool f){
    17     for (int i=0; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
    18     for (int i=1; i<n; i<<=1){
    19         int wn=ksm(3,f ? (mod-1)/(i<<1) : (mod-1)-(mod-1)/(i<<1));
    20         for (int p=i<<1,j=0; j<n; j+=p){
    21             int w=1;
    22             for (int k=0; k<i; k++,w=1ll*w*wn%mod){
    23                 int x=a[j+k],y=1ll*w*a[i+j+k]%mod;
    24                 a[j+k]=(x+y)%mod; a[i+j+k]=(x-y+mod)%mod;
    25             }
    26         }
    27     }
    28     if (f) return;
    29     int inv=ksm(n,mod-2);
    30     for (int i=0; i<n; i++) a[i]=1ll*a[i]*inv%mod;
    31 }
    32 
    33 void Inv(int a[],int b[],int l){
    34     if (l==1){ b[0]=ksm(a[0],mod-2); return; }
    35     Inv(a,b,l>>1); int n=1,L=0;
    36     for (; n<=l; n<<=1) L++;
    37     for (int i=0; i<n; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
    38     for (int i=0; i<l; i++) tmp[i]=a[i],tmp[i+l]=0;
    39     DFT(tmp,n,1); DFT(b,n,1);
    40     for (int i=0; i<n; i++) tmp[i]=1ll*b[i]*(2-1ll*tmp[i]*b[i]%mod+mod)%mod;
    41     DFT(tmp,n,0);
    42     for (int i=0; i<l; i++) b[i]=tmp[i],b[i+l]=0;
    43 }
    44 
    45 int main(){
    46     n=100000;
    47     fac[0]=1; rep(i,1,n) fac[i]=1ll*fac[i-1]*i%mod;
    48     inv[n]=ksm(fac[n],mod-2);
    49     for (int i=n-1; ~i; i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    50     rep(i,1,n) h[i]=mod-inv[i]; h[0]=1;
    51     for (m=1; m<=n; m<<=1); Inv(h,g,m);
    52     for (int i=1; i<m; i++) f[i]=g[i];
    53     f[0]=(g[0]-1+mod)%mod; m<<=1;
    54     DFT(f,m,1); DFT(g,m,1);
    55     for (int i=0; i<m; i++) f[i]=1ll*f[i]*g[i]%mod;
    56     DFT(f,m,0); DFT(g,m,0);
    57     for (scanf("%d",&T); T--; ) scanf("%d",&n),printf("%lld
    ",1ll*f[n]*ksm(g[n],mod-2)%mod);
    58     return 0;
    59 }
  • 相关阅读:
    OGG实验:喂奶间隔数据表通过OGG配置同步
    Oracle Exadata 学习笔记之核心特性Part1
    js 表格指定列,根据相同值实现跨行合并
    tr td同时添加点击事件
    Oracle 分页查询
    tomcat启动时运行指定的java类
    application/x-www-form-urlencoded与multipart/form-data与application/json的区别 精析
    nodejs中thiskeyword的问题
    AlphaGo 开源项目研究(1)
    LeetCode -- Best Time to Buy and Sell Stock II
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10227080.html
Copyright © 2020-2023  润新知