Luogu P5850 calc加强版

Posted cjoiershiina-mashiro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu P5850 calc加强版相关的知识,希望对你有一定的参考价值。

Link

[ans_n=[x^n]prodlimits_{i=1}^k(1+ix)=[x^n]exp(sumlimits_{i=1}^kln(1+ix))=[x^n]exp(sumlimits_{jge1}frac{(-1)^{j+1}sumlimits_{i=1}^ki^j}jx^j)\sumlimits_{jge0}sumlimits_{i=1}^kfrac{i^jx^j}{j!}=sumlimits_{i=0}^kexp(ix)=frac{exp((k+1)x)-1}{exp(x)-1} ]

#include<cstdio>
#include<cstring>
#include<algorithm>
const int N=1<<20|1,P=998244353;
int k,n,len,fac[N],inv[N],ifac[N],rev[N],w[N];
int getlen(int n){return 1<<(32-__builtin_clz(n));}
int inc(int a,int b){return a+=b-P,a+(a>>31&P);}
int dec(int a,int b){return a-=b,a+(a>>31&P);}
int mul(int a,int b){return 1ll*a*b%P;}
int pow(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
void init(int n)
{
    int lim=1<<(len=32-__builtin_clz(n)),g=pow(3,(P-1)/lim);
    w[lim>>1]=1,fac[0]=ifac[0]=inv[0]=fac[1]=ifac[1]=inv[1]=1;
    for(int i=1;i<lim;++i) rev[i]=(rev[i>>1]>>1)|(i&1? lim>>1:0);
    for(int i=(lim>>1)+1;i<lim;++i) w[i]=mul(w[i-1],g);
    for(int i=(lim>>1)-1;i;--i) w[i]=w[i<<1];
    for(int i=2;i<=lim;++i) fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[i-1],inv[i]=mul(inv[P%i],P-P/i));
}
void NTT(int*a,int lim,int f)
{
    if(!~f) std::reverse(a+1,a+lim);
    for(int i=0,x=len-__builtin_ctz(lim);i<lim;++i) if(i<rev[i]>>x) std::swap(a[i],a[rev[i]>>x]);
    for(int i=1;i<lim;i<<=1) for(int j=0,d=i<<1;j<lim;j+=d) for(int k=0,x;k<i;++k) x=mul(a[i+j+k],w[i+k]),a[i+j+k]=dec(a[j+k],x),a[j+k]=inc(a[j+k],x);
    if(!~f) for(int i=0,x=P-(P-1)/lim;i<lim;++i) a[i]=mul(a[i],x);
}
void Inv(int*a,int*b,int deg)
{
    if(deg==1) return b[0]=pow(a[0],P-2),void();
    static int t[N];int lim=getlen(deg*2-2);
    Inv(a,b,(deg+1)>>1),memcpy(t,a,deg<<2),memset(t+deg,0,(lim-deg)<<2),NTT(t,lim,1),NTT(b,lim,1);
    for(int i=0;i<lim;++i) b[i]=mul(dec(2,mul(b[i],t[i])),b[i]);
    NTT(b,lim,-1),memset(b+deg,0,(lim-deg)<<2);
}
void Der(int*a,int*b,int deg){for(int i=1;i<deg;++i)b[i-1]=mul(a[i],i);b[deg-1]=0;}
void Int(int*a,int*b,int deg){for(int i=1;i<deg;++i)b[i]=mul(a[i-1],inv[i]);b[0]=0;}
void Ln(int*a,int*b,int deg)
{
    static int t[N];int lim=getlen(deg*2-2);
    Inv(a,t,deg),Der(a,b,deg),NTT(t,lim,1),NTT(b,lim,1);
    for(int i=0;i<lim;++i) t[i]=mul(t[i],b[i]);
    NTT(t,lim,-1),Int(t,b,deg),memset(t,0,lim<<2),memset(b+deg,0,(lim-deg)<<2);
}
void Exp(int*a,int*b,int deg)
{
    if(deg==1) return b[0]=1,void();
    static int t[N];int lim=getlen(deg*2-2);
    Exp(a,b,(deg+1)>>1),Ln(b,t,deg);
    for(int i=0;i<deg;++i) t[i]=dec(a[i],t[i]);
    memset(t+deg,0,(lim-deg)<<2),++t[0],NTT(t,lim,1),NTT(b,lim,1);
    for(int i=0;i<lim;++i) b[i]=mul(b[i],t[i]);
    NTT(b,lim,-1),memset(b+deg,0,(lim-deg)<<2),memset(t+deg,0,(lim-deg)<<2);
}
void Get_Inv(int*a,int*b,int n)
{
    static int t[N];
    Inv(a,t,n),memcpy(b,t,4*n);
}
void Get_Exp(int*a,int*b,int n)
{
    static int t[N];
    Exp(a,t,n),memcpy(b,t,4*n);
}
int f[N],g[N];char obuf[1<<23],*oS=obuf;
void write(int x){if(!x)return;write(x/10),*oS++=48+x%10;}
void print(int x){if(!x)*oS++=‘0‘;else write(x);*oS++=‘
‘;}
int main()
{
    scanf("%d%d",&k,&n),init(2*n);int lim=getlen(2*n);
    for(int i=0,pw=k;i<=n;++i) f[i]=mul(pw,ifac[i+1]),g[i]=i&1? P-ifac[i+1]:ifac[i+1],pw=mul(pw,k);
    Get_Inv(g,g,n+1),NTT(f,lim,1),NTT(g,lim,1);
    for(int i=0;i<lim;++i) g[i]=mul(f[i],g[i]);
    NTT(g,lim,-1),memset(f,0,4*lim);
    for(int i=1;i<=n;++i) f[i]=mul(fac[i-1],g[i]),~i&1? f[i]=dec(0,f[i]):0;
    Get_Exp(f,f,n+1);
    for(int i=1;i<=n;++i) print(mul(fac[i],f[i]));
    fwrite(obuf,1,oS-obuf,stdout);
}

以上是关于Luogu P5850 calc加强版的主要内容,如果未能解决你的问题,请参考以下文章

luogu P1120 小木棍 [数据加强版]

Luogu1006 传纸条 与 Luogu P2045方格取数加强版 (费用流)

Luogu P1429 平面最近点对(加强版)

luogu P5442 XR-2约定 (加强版)

luogu4931.情侣?给我烧了!(加强版)(错位排列)

题解luogu2045 方格取数游戏加强版