求助多项式板子
  • 板块学术版
  • 楼主zyxawa
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/7/1 21:46
  • 上次更新2024/7/1 22:09:56
查看原帖
求助多项式板子
673294
zyxawa楼主2024/7/1 21:46

跑得飞慢,求一些减少常数的写法

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<ll> poly;
#define fix(f,n) f.resize(n+1)
int rev[2100001],inv[200001],w[2100001];
const int mod=998244353,G=3,I=86583718;
auto add=[](ll x,ll y){return x+y>=mod?x+y-mod:x+y;};
auto del=[](ll x,ll y){return x<y?x-y+mod:x-y;};
ll qpow(ll a,ll b){
    ll s=1;
    for(;b;b>>=1,a=a*a%mod) if(b&1) s=s*a%mod;
    return s;
}
void init(int n){
    inv[1]=w[n]=1,w[n|1]=qpow(G,(mod-1)/n);
    for(int i=2;i<n;i++) w[n|i]=1ll*w[n|i-1]*w[n|1]%mod;
    for(int i=n-1;i>=1;i--) w[i]=w[i<<1];
    for(int i=2;i<=200000;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
}
void ntt(poly &f,int c,int n){
    fix(f,n-1);
    for(int i=0;i<n;i++) if(i<rev[i]) swap(f[i],f[rev[i]]);
    for(int k=1;k<n;k<<=1){
        for(int i=0;i<n;i+=k+k){
            for(int j=i,*p=w+k+k;j<i+k;j++){
                int x=f[j],y=f[j+k]*(*p++)%mod;
                f[j+k]=del(x,y);
                f[j]=add(x,y);
            }
        }
    }
    if(!c) reverse(f.begin()+1,f.begin()+n);
}
poly operator+(poly f,poly g){
    fix(f,max(f.size(),g.size())-1);
    for(int i=0;i<g.size();i++) f[i]=add(f[i],g[i]);
    return f;
}
poly operator-(poly f,poly g){
    fix(f,max(f.size(),g.size())-1);
    for(int i=0;i<g.size();i++) f[i]=del(f[i],g[i]);
    return f;
}
poly operator*(poly f,ll g){
    for(int i=0;i<f.size();i++) f[i]=f[i]*g%mod;
    return f;
}
poly operator*(poly f,poly g){
    int m=f.size()+g.size()-2,n=1<<__lg(m)+1,inv=0;
    for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|(i&1?n>>1:0);
    ntt(f,1,n);
    ntt(g,1,n);
    inv=qpow(n,mod-2);
    for(int i=0;i<n;i++) f[i]=f[i]*g[i]%mod;
    ntt(f,0,n);
    fix(f,m);
    for(int i=0;i<=m;i++) f[i]=f[i]*inv%mod;
    return f;
}
poly Der(poly f){
    for(int i=1;i<f.size();i++) f[i-1]=f[i]*i%mod;
    f.pop_back();
    return f;
}
poly Int(poly f){
    f.push_back(0);
    for(int i=f.size()-1;i>=1;i--) f[i]=f[i-1]*inv[i]%mod;
    return f[0]=0,f;
}
poly Inv(poly f){
    int n=f.size(),lst=f.size()-1,inv=0;
    poly g(1,qpow(f[0],mod-2));
    fix(f,n*2);
    for(int m=2;m/2<n;m<<=1){
        poly h(f.begin(),f.begin()+m);
        for(int i=0;i<m*2;i++) rev[i]=(rev[i>>1]>>1)|(i&1?m:0);
        ntt(g,1,m*2);
        ntt(h,1,m*2);
        inv=qpow(m*2,mod-2);
        for(int i=0;i<m*2;i++) g[i]=del(add(g[i],g[i]),g[i]*g[i]%mod*h[i]%mod);
        ntt(g,0,m*2);
        fix(g,m);
        for(int i=0;i<=m;i++) g[i]=g[i]*inv%mod;
    }
    fix(g,lst);
    return g;
}
poly operator/(poly f,poly g){
    int n=f.size()-1,m=g.size()-1;
    if(n-m+1<0) return poly();
    reverse(f.begin(),f.end());
    reverse(g.begin(),g.end());
    fix(f,n-m+1);
    fix(g,n-m+1);
    poly h=f*Inv(g);
    fix(h,n-m);
    reverse(h.begin(),h.end());
    return h;
}
poly operator%(poly f,poly g){
    poly h=f-f/g*g;
    fix(h,(ll)g.size()-2);
    return h;
}
poly Ln(poly f){
    poly g=Der(f)*Inv(f);
    fix(g,(ll)f.size()-2);
    return Int(g);
}
poly Exp(poly f){
    int n=f.size(),lst=f.size()-1;
    poly g(1,1);
    fix(f,n*2);
    for(int m=2;m/2<n;m<<=1){
        poly h(f.begin(),f.begin()+m);
        h[0]++;
        fix(g,m);
        g=g*(h-Ln(g));
    }
    fix(g,lst);
    return g;
}
poly Sqrt(poly f){
    int n=f.size(),lst=f.size()-1;
    poly g(1,sqrt(f[0]));
    fix(f,n*2);
    for(int m=2;m/2<n;m<<=1){
        poly h(f.begin(),f.begin()+m);
        fix(g,m);
        g=(g+h*Inv(g))*(mod+1>>1);
    }
    fix(g,lst);
    return g;
}
poly Sin(poly f){
    poly g=Exp(f*I),h=Inv(g);
    return f=(g-h)*qpow(2*I,mod-2);
}
poly Cos(poly f){
    poly g=Exp(f*I),h=Inv(g);
    return f=(g+h)*qpow(2,mod-2);
}
poly Pow(poly f,char *k){
    ll n=f.size()-1,b=0,k1=0,k2=0,k3=0,val=0;
    while(b<=n&&!f[b]) b++;
    for(int i=1;k[i];i++) k1=(k1*10+k[i]-48)%mod,k2=(k2*10+k[i]-48)%(mod-1);
    for(int i=1;k[i]&&i<=6;i++) k3=k3*10+k[i]-48;
    if(b*k1>n||k3>n&&!f[0]){
        for(int i=0;i<=n;i++) f[i]=0;
        return f;
    }
    for(int i=0;i<=n;i++) f[i]=(i+b<=n?f[i+b]:0);
    val=qpow(f[0],k2);
    b*=k1;
    f=Exp(Ln(f*qpow(f[0],mod-2))*k1);
    for(int i=n;i>=b;i--) f[i]=f[i-b]*val%mod;
    for(int i=0;i<b;i++) f[i]=0;
    return f;
}
int main(){
    init(1<<20);

    return 0;
}
2024/7/1 21:46
加载中...