zoukankan      html  css  js  c++  java
  • BZOJ4555: [Tjoi2016&Heoi2016]求和

    $n<=100000$求$sum_{i=0}^{n}sum_{j=0}^{i}s(i,j)*2^j*(j!)$,其中$S(i,j)$表示第二类斯特林数。

    方法一:多项式求逆。不会。

    方法二:

    $S(i,j)=frac{1}{j!}sum_{k=0}^{j}(-1)^kC_j^k(j-k)^i$,代入得(这里由于j>i是S(i,j)=0因此j可以枚举到n)

    $sum_{i=0}^{n}sum_{j=0}^{i}s(i,j)*2^j*(j!)$

    $=sum_{i=0}^{n}sum_{j=0}^{n}2^j*(j!)*frac{1}{j!}sum_{k=0}^{j}(-1)^kC_j^k(j-k)^i$

    $=sum_{j=0}^{n}2^jsum_{k=0}^{j}(-1)^kC_j^ksum_{i=0}^{n}(j-k)^i$

    $=sum_{j=0}^{n}2^j*(j!)sum_{k=0}^{j}frac{(-1)^k}{k!}frac{sum_{i=0}^{n}(j-k)^i}{(j-k)!}$

    后面俩卷积。搞定。

    注意预处理时的边界情况。比如i=0,i=1,i=2之类的。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 //#include<map>
     6 #include<math.h>
     7 //#include<time.h>
     8 //#include<complex>
     9 #include<algorithm>
    10 using namespace std;
    11  
    12 int n,m,wei;
    13 #define maxn 262222
    14 const int mod=998244353,G=3; int rev[maxn];
    15 
    16 int powmod(int a,int b)
    17 {
    18     int ans=1;
    19     while (b)
    20     {
    21         if (b&1) ans=1ll*ans*a%mod;
    22         a=1ll*a*a%mod; b>>=1;
    23     }
    24     return ans;
    25 }
    26 
    27 void dft(int *a,int n,int type)
    28 {
    29     if (!rev[1]) for (int i=0;i<n;i++)
    30     {
    31         rev[i]=0;
    32         for (int j=0;j<wei;j++) rev[i]|=((i>>j)&1)<<(wei-j-1);
    33     }
    34     for (int i=0;i<n;i++) if (i<rev[i]) {int t=a[i]; a[i]=a[rev[i]]; a[rev[i]]=t;}
    35     for (int i=1;i<n;i<<=1)
    36     {
    37         int w=powmod(G,(mod-1)/(i<<1));
    38         if (type==-1) w=powmod(w,mod-2);
    39         for (int j=0,p=i<<1;j<n;j+=p)
    40         {
    41             int t=1;
    42             for (int k=0;k<i;k++,t=1ll*t*w%mod)
    43             {
    44                 int tmp=1ll*t*a[j+k+i]%mod;
    45                 a[j+k+i]=(a[j+k]-tmp+mod)%mod;
    46                 a[j+k]=(a[j+k]+tmp)%mod;
    47             }
    48         }
    49     }
    50     if (type==-1)
    51     {
    52         int inv=powmod(n,mod-2);
    53         for (int i=0;i<n;i++) a[i]=1ll*a[i]*inv%mod;
    54     }
    55 }
    56 
    57 void ntt(int *a,int *b,int *c)
    58 {
    59     dft(a,n,1); dft(b,n,1);
    60     for (int i=0;i<n;i++) c[i]=1ll*a[i]*b[i]%mod;
    61     dft(c,n,-1);
    62 }
    63 
    64 int two[maxn],fac[maxn],inv[maxn],ni[maxn],g[maxn],h[maxn],f[maxn];
    65 int main()
    66 {
    67     scanf("%d",&n);
    68     two[0]=1; for (int i=1;i<=n;i++) two[i]=(two[i-1]<<1)%mod;
    69     fac[0]=1; for (int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod;
    70     inv[n]=powmod(fac[n],mod-2); for (int i=n;i;i--) inv[i-1]=inv[i]*1ll*i%mod;
    71     ni[1]=1; for (int i=2;i<=n;i++) ni[i]=ni[mod%i]*1ll*(mod-mod/i)%mod;
    72     
    73     g[0]=1; g[1]=n+1; g[2]=(powmod(2,n+1)-1)*1ll*ni[2]%mod;
    74     for (int i=3;i<=n;i++) g[i]=1ll*(mod/(i-1)*1ll*ni[mod%(i-1)]%mod)*(mod+1-powmod(i,n+1))%mod*inv[i]%mod;
    75     for (int i=0;i<=n;i++) h[i]=1ll*((i&1)?mod-1:1)*inv[i]%mod;
    76     
    77     m=n+n; for (n=1,wei=0;n<=m;n<<=1,wei++);
    78     ntt(h,g,f); m>>=1;
    79     int ans=0;
    80     for (int i=0;i<=m;i++) ans=(ans+1ll*two[i]*fac[i]%mod*f[i]%mod)%mod;
    81     printf("%d
    ",ans);
    82     return 0;
    83 }
    View Code

    好方法一会了。

    从定义上出发,$s(i,j)$是$i$个数分成$j$个集合,再乘个$j!$就排列,再乘个$2^j$就染黑白。

    OK可以递推了,枚举最后一个集合是谁,$f(i)=sum_{j=0}^{i}s(i,j)*2^j*(j!)=sum_{j=1}^{i}2C_i^jf(i-j)=sum_{j=1}^{i}frac{2*i!*f(i-j)}{j!(i-j)!}$

    $i!$提出来丢左边,$frac{f(i)}{i!}=sum_{j=1}^{i}frac{2}{j!}frac{f(i-j)}{(i-j)!}$,一卷积。

    令$g(i)=frac{f(i)}{i!}$,$h(i)=frac{2}{i!}$,要卷积就来生成函数吧,现在$g(x)$,$h(x)$表示各自的生成函数。

    打住!这里卷积不希望有$h(0)g(i)$这项!!那钦定$h(x)$常数项为0.

    等等$g(x)$的常数项是1啊!那就$g=g*h+1$。

    于是$g=frac{1}{1-h}$。

    搞定。求(1-h)的逆即可。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 //#include<map>
     6 #include<math.h>
     7 //#include<time.h>
     8 //#include<complex>
     9 #include<algorithm>
    10 using namespace std;
    11 
    12 int n,m,wei;
    13 #define maxn 262222
    14 const int mod=998244353,G=3; int rev[maxn];
    15 
    16 int powmod(int a,int b)
    17 {
    18     int ans=1;
    19     while (b)
    20     {
    21         if (b&1) ans=1ll*ans*a%mod;
    22         a=1ll*a*a%mod; b>>=1;
    23     }
    24     return ans;
    25 }
    26 
    27 void dft(int *a,int n,int type)
    28 {
    29     int wei=-1,tnt=n;
    30     while (tnt) wei++,tnt>>=1;
    31     for (int i=0;i<n;i++)
    32     {
    33         rev[i]=0;
    34         for (int j=0;j<wei;j++) rev[i]|=((i>>j)&1)<<(wei-j-1);
    35     }
    36     for (int i=0;i<n;i++) if (i<rev[i]) {int t=a[i]; a[i]=a[rev[i]]; a[rev[i]]=t;}
    37     for (int i=1;i<n;i<<=1)
    38     {
    39         int w=powmod(G,(mod-1)/(i<<1));
    40         if (type==-1) w=powmod(w,mod-2);
    41         for (int j=0,p=i<<1;j<n;j+=p)
    42         {
    43             int t=1;
    44             for (int k=0;k<i;k++,t=1ll*t*w%mod)
    45             {
    46                 int tmp=1ll*t*a[i+j+k]%mod;
    47                 a[j+k+i]=(a[j+k]-tmp+mod)%mod;
    48                 a[j+k]=(a[j+k]+tmp)%mod;
    49             }
    50         }
    51     }
    52     if (type==-1)
    53     {
    54         int inv=powmod(n,mod-2);
    55         for (int i=0;i<n;i++) a[i]=1ll*a[i]*inv%mod;
    56     }
    57 }
    58 
    59 int fac[maxn],inv[maxn],h[maxn],g[maxn],tmp[maxn];
    60 void nee(int *a,int n,int *ans)
    61 {
    62     if (n==1) {ans[0]=powmod(a[0],mod-2); return;}
    63     nee(a,n>>1,ans);
    64     for (int i=0;i<(n>>1);i++) tmp[i]=a[i]; for (int i=(n>>1);i<n;i++) tmp[i]=0;
    65     dft(ans,n,1); dft(tmp,n,1);
    66     for (int i=0;i<n;i++) ans[i]=((ans[i]+ans[i]-1ll*ans[i]*ans[i]%mod*tmp[i]%mod)+mod)%mod;
    67     dft(ans,n,-1); for (int i=n>>1;i<n;i++) ans[i]=0;
    68 }
    69 
    70 int main()
    71 {
    72     scanf("%d",&n);
    73     fac[0]=1; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*1ll*i%mod;
    74     inv[n]=powmod(fac[n],mod-2); for (int i=n;i;i--) inv[i-1]=1ll*inv[i]*i%mod;
    75     h[0]=1; for (int i=1;i<=n;i++) h[i]=(mod+mod-inv[i]-inv[i])%mod;
    76     
    77     m=n+n; for (n=1,wei=0;n<=m;n<<=1,wei++);
    78     nee(h,n,g); m>>=1;
    79     int ans=0;
    80     for (int i=0;i<=m;i++) ans=(ans+1ll*fac[i]*g[i])%mod;
    81     printf("%d
    ",ans);
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    HTML初步学习7
    HTML初步学习6
    HTML初步学习5
    HTML初步学习4
    poj3449Geometric Shapes
    poj2074Line of Sight(直线相交)
    2014 Multi-University Training Contest 4
    poj3347Kadj Squares
    poj1556The Doors
    poj3608Bridge Across Islands(凸包间最小距离)
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8479487.html
Copyright © 2011-2022 走看看