大常数选手重伤倒地!
查看原帖
大常数选手重伤倒地!
1024338
Le0Chan楼主2024/3/13 11:06

loj 上的仙人掌计数时限 3s3s。此题可以用上题做法套个 exp⁡\exp,但是时限 2s2s。我在 loj 上跑了 2.7s2.7s,请求开大时限。

#include <bits/stdc++.h>
using namespace std;
namespace Le0{
#define il inline 
const int mod=998244353,gg=3,N=3e5+5;
struct poly{
    vector<int> a;
    il int& operator[](int x){return a[x];}
    il void re(int x){while(a.size()<x) a.push_back(0);}
    il void cl(){vector<int> ().swap(a);}
}a,b;
int n,lim,ct,gi,T;
int rv[N],fac[N],ifac[N];
il int qp(int a,int b){
    int as=1;
    while(b){
        if(b&1) as=1ll*as*a%mod;
        a=1ll*a*a%mod;
        b>>=1;
    }
    return as;
}
il void ntt(poly &a,int op){
    for(int i=0;i<lim;i++) if(i<rv[i]) swap(a[i],a[rv[i]]);
    for(int mid=1;mid<lim;mid<<=1){
        int rt=qp(op==1?gg:gi,(mod-1)/(mid*2));
        for(int j=0;j<lim;j+=mid*2){
            int w=1;
            for(int k=0;k<mid;k++){
                int x=a[j+k],y=1ll*w*a[j+k+mid]%mod;
                a[j+k]=(x+y)%mod,a[j+k+mid]=(x-y+mod)%mod;
                w=1ll*w*rt%mod;
            }
        }
    }
    if(op==1) return;
    int inv=qp(lim,mod-2);
    for(int i=0;i<lim;i++) a[i]=1ll*a[i]*inv%mod;
}
il poly mul(poly a,poly b,int len){
    lim=1,ct=-1;
    while(lim<=(len-1)*2) lim<<=1,ct++;
    for(int i=0;i<lim;i++) rv[i]=(rv[i>>1]>>1)|((i&1)<<ct);
    a.re(lim);b.re(lim);
    for(int i=len;i<lim;i++) a[i]=b[i]=0;
    ntt(a,1);ntt(b,1);
    for(int i=0;i<lim;i++) a[i]=1ll*a[i]*b[i]%mod;
    ntt(a,-1);
    for(int i=len;i<lim;i++) a[i]=0;
    return a; 
}
il void inv(poly a,poly &b,int len){
    if(len==1){
        b[0]=qp(a[0],mod-2);
        return;
    }
    inv(a,b,len+1>>1);
    poly G0=b,F=a;
    F=mul(F,mul(G0,G0,len),len);
    for(int i=0;i<len;i++) b[i]=(2ll*G0[i]%mod-F[i]+mod)%mod;
}
il void ln(poly &a,int len){
    poly b;b.re(len);
    inv(a,b,len);
    poly c;c.re(len);
    for(int i=0;i<len-1;i++) c[i]=1ll*a[i+1]*(i+1)%mod;
    c=mul(c,b,len);
    for(int i=1;i<len;i++) a[i]=1ll*c[i-1]*qp(i,mod-2)%mod; 
    a[0]=0;
}
il void exp(poly a,poly &b,int len){
    if(len==1){
        b[0]=1;
        return;
    }
    exp(a,b,len+1>>1);
    poly f=b;ln(f,len);
    a[0]++;
    for(int i=0;i<len;i++) f[i]=(mod-f[i]+a[i])%mod;
    b=mul(b,f,len);
}
il void Newton(poly &a,int len){
    if(len==1) return;
    Newton(a,len+1>>1);
    poly a2=mul(a,a,len);
    poly F,iF;F.re(len);iF.re(len);
    for(int i=0;i<len;i++) F[i]=mod-2ll*a[i]%mod;
    F[0]+=2;
    inv(F,iF,len);
    poly F2=mul(F,F,len);
    poly iF2;iF2.re(len);
    inv(F2,iF2,len);
    poly b;b.re(len);
    for(int i=0;i<len;i++) b[i]=(2ll*a[i]%mod-a2[i]+mod)%mod;
    b=mul(b,iF,len);
    poly c;c.re(len);
    exp(b,c,len);
    poly res;res.re(len);
    for(int i=1;i<len;i++) res[i]=c[i-1];
    poly d;d.re(len);
    for(int i=0;i<len;i++) d[i]=(4ll*a[i]%mod-2ll*a2[i]%mod+mod)%mod;
    d=mul(d,iF2,len);d[0]++;
    d=mul(d,res,len);
    for(int i=0;i<len;i++) d[i]=mod-d[i];
    d[0]++;
    poly id;id.re(len);
    inv(d,id,len);
    for(int i=0;i<len;i++) res[i]=(a[i]-res[i]+mod)%mod;
    res=mul(res,id,len);
    for(int i=0;i<len;i++) a[i]=(a[i]-res[i]+mod)%mod;
}
void init(){
    fac[0]=ifac[0]=1;
    for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod;
    ifac[n]=qp(fac[n],mod-2);
    for(int i=n-1;i>=1;i--) ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
}
int main(){
    cin>>n;gi=qp(gg,mod-2);
    a.re(n+1);b.re(n+1);
    init();
    Newton(a,n+1);
    for(int i=1;i<=n;i++) a[i]=1ll*a[i]*qp(i,mod-2)%mod;
    exp(a,b,n+1);
    cout<<1ll*b[n]*fac[n]%mod<<'\n';
    return 0;
}
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0);
    return Le0::main();
}
2024/3/13 11:06
加载中...