【全家福】多项式的各种板子

写完帕秋莉的超级多项式于是正好贴个模板大汇总(带优化的那种...)

//by Judge
#include<bits/stdc++.h>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
#define ll long long
using namespace std;
const int mod=998244353;
const int iG=332748118;
const int M=3e5+3;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int inc(int x,int y){return (x+y)%mod;}
inline int dec(int x,int y){return (x-y+mod)%mod;}
inline int Dec(int x,int y){return x<y?x-y+mod:x-y;}
inline int Inc(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int read(){ int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int CCF=-1,Z;
inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
inline void print(int x,char chr=' '){
    if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
} int n,k,d,limit; arr a,b,r[21],lg,inv,G[2];
inline int qpow(Rg int x,Rg int p=mod-2,Rg int s=1){
    for(;p;p>>=1,x=mul(x,x)) if(p&1) s=mul(s,x); return s;
}
inline void prep(int n){
    inv[1]=1; for(limit=1;limit<=n;limit<<=1);
    fp(i,2,limit) inv[i]=mul(mod-mod/i,inv[mod%i]);
    fp(d,1,19){ lg[1<<d]=d; fp(i,0,(1<<d)-1)
        r[d][i]=(r[d][i>>1]>>1)|((i&1)<<(d-1));
    }
    for(Rg int t=(mod-1)>>1,i=1,x,y;i<262144;i<<=1,t>>=1){
        x=qpow(3,t),y=qpow(iG,t),G[0][i]=G[1][i]=1;
        fp(k,1,i-1) G[1][i+k]=mul(G[1][i+k-1],x),G[0][i+k]=mul(G[0][i+k-1],y);
    }
}
inline void NTT(int* a,int tp){
    fp(i,0,limit-1) if(i<r[d][i]) swap(a[i],a[r[d][i]]);
    for(Rg int mid=1;mid<limit;mid<<=1){ int I=mid<<1;
        for(Rg int j=0,x,y;j<limit;j+=I) fp(k,0,mid-1)
            x=a[j+k],y=mul(G[tp][mid+k],a[j+k+mid]),
            a[j+k]=(x+y)%mod,a[j+k+mid]=(x-y+mod)%mod;
    }
    if(tp) return ; fp(i,0,limit-1) a[i]=mul(a[i],inv[limit]);
}
inline void init(Rg int n){ d=0;
    for(limit=1;limit<=n;limit<<=1)++d;
}
void Inv(int* a,int* b,int n){
    static arr C,D; if(n==1) return b[0]=qpow(a[0]),void();
    Inv(a,b,n>>1),init(n); fp(i,0,n-1) C[i]=a[i],D[i]=b[i];
    fp(i,n,limit-1) C[i]=D[i]=0; NTT(C,1),NTT(D,1);
    fp(i,0,limit-1) C[i]=mul(C[i],mul(D[i],D[i])); NTT(C,0);
    fp(i,0,n-1) b[i]=dec(inc(b[i],b[i]),C[i]); fp(i,n,limit-1) b[i]=0;
}
void Sqrt(int* a,int* b,int n){
    static arr D,F; if(n==1) return b[0]=sqrt(a[0]),void();
    Sqrt(a,b,n>>1); fp(i,0,n<<1) F[i]=0;
    Inv(b,F,n),init(n); fp(i,0,n-1) D[i]=a[i];
    fp(i,n,limit-1) D[i]=0; NTT(D,1),NTT(b,1),NTT(F,1);
    fp(i,0,limit-1) b[i]=mul(inc(b[i],mul(D[i],F[i])),inv[2]);
    NTT(b,0); fp(i,n,limit-1) b[i]=0;
    memset(D,0,limit<<2),memset(F,0,limit<<2);
}
inline void Direv(int* a,int* b,int n){
    fp(i,1,n-1) b[i-1]=mul(a[i],i); b[n-1]=b[n]=0;
}
inline void Inter(int* a,int* b,int n){
    fp(i,1,n-1) b[i]=mul(a[i-1],inv[i]); b[0]=0;
}
inline void Ln(int* a,int* b,int n){
    static arr A,B; Direv(a,A,n),Inv(a,B,n);
    init(n),NTT(A,1),NTT(B,1);
    fp(i,0,limit-1) A[i]=mul(A[i],B[i]);
    NTT(A,0),Inter(A,b,limit);
    memset(A,0,limit<<2),memset(B,0,limit<<2);
}
inline void Exp(int* a,int* b,int n){
    static arr F; if(n==1) return b[0]=1,void();
    Exp(a,b,n>>1),Ln(b,F,n),init(n);
    F[0]=dec(a[0]+1,F[0]); fp(i,1,n-1) F[i]=dec(a[i],F[i]);
    NTT(F,1),NTT(b,1); fp(i,0,limit-1) b[i]=mul(b[i],F[i]);
    NTT(b,0); fp(i,n,limit-1) b[i]=0; memset(F,0,limit<<2);
}
inline void Pow(int* a,int* b,int n,int k){
    static arr F; memset(F,0,n<<2),Ln(a,F,n);
    fp(i,0,n-1) F[i]=mul(F[i],k); Exp(F,b,n);
}
int main(){ prep(1<<19);
    return 0;
}

原文地址:https://www.cnblogs.com/Judge/p/10735653.html

时间: 2024-10-15 20:48:19

【全家福】多项式的各种板子的相关文章

LibreOJ #108. 多项式乘法

二次联通门 : LibreOJ #108. 多项式乘法 /* LibreOJ #108. 多项式乘法 FFT板子题 不行啊...跑的还是慢 应该找个机会学一学由乃dalao的fft 或者是毛爷爷的fft,跑的真是快啊... */ #include <cstdio> #include <iostream> #include <cmath> const int BUF = 12312312; char Buf[BUF], *buf = Buf; inline void re

多项式板子

不包含MTT的板子, 这种有的话就弃疗了 /* 求逆迭代 B = 2B - AB^2 系数反转 F(1 / x) * x ^ n 除法迭代 已知 F(x) = Q(x) * G(x) + R(x) F(x),G(x) 求Q(x) R(x) F(x) = Q(x) * G(x) + R(x) mod x ^ {n + 1} F(1 / x) = Q(1 / x) * G(1 / x) + R(1 / x) mod x ^ {n + 1} Frev(x) = Qrev(x) * Grev(x) +

多项式板子&#183;新

之前写过一个vector的多项式汇总...不过常数特别大 最近事儿比较少,准备写一个int[]的 目前没写完,先打了发多项式求逆,蛙了好几发... 最后发现递归下去回来之后忘了清系数了... int[]版的主要是数组大小和高位系数比较恶心,还有数组清空啥的... 不过常数肯定比vector小很多,所以还是尝试写一下好了 #include <cstdio> #include <algorithm> using namespace std; const int p = 99824435

多项式板子(待补充)

已经实现的操作 乘法NTT, mul 求逆inverse 积分integral,微分deriv 对数ln 指数exp 快速幂power(常数项为\(1\)) 开根sqrt(常数项为\(1\)) 说明 所有操作都是原地操作,以后有空改(大量copy还是比较麻烦.耗时) 常数还可以 Code const int N = 262144, G = 3, iG = 332748118, p = 998244353, maxlen = N; inline int add(int x, int y){retu

UOJ #34 多项式乘法

题目链接:多项式乘法 保存一发FFT与NTT板子. 学习链接:从多项式乘法到快速傅里叶变换 FFT NTT 注意差值回来的时候不取反也是可以的,只不过需要把数组\(reverse\)一下(根据单位复数根的性质应该不难理解) 代码(FFT): #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<co

【uoj34】 多项式乘法

http://uoj.ac/problem/34 (题目链接) 题意 求两个多项式的乘积 Solution 挂个FFT板子.当然,是hzwer的板子→_→ 细节 FFT因为要满足n是2的幂,所以注意数组大小. 代码 // uoj34 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<complex> #include<cst

[学习笔记] 多项式与快速傅里叶变换(FFT)基础

引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积(或者多项式乘法/高精度乘法), 而代码量却非常小. 博主一年半前曾经因COGS的一道叫做"神秘的常数 $\pi$"的题目而去学习过FFT, 但是基本就是照着板子打打完并不知道自己在写些什么鬼畜的东西OwO 不过...博主这几天突然照着算法导论自己看了一遍发现自己似乎突然意识到了什么OwO然后就打了一道板子题还1A了OwO再加上午考试差点AK

多项式多点求值和插值

本文以存板子为主= = 对于比较一般的情况,n次多项式在n个点求值和用n个点插值可以做到,并且这也是下界. 多项式多点求值 给一个多项式F和一堆值,求出. 设,. 那么对于,,对于,.递归即可. 多项式多点插值 给一堆值.,要求求出一个n-1次多项式满足. 考虑拉格朗日插值:. 我们先考虑对于每个i,如何求出.设,那么我们就是要求. 取的时候这个式子分子分母都为0,那么我们可以用洛必达法则,这个式子就等于.那么我们可以用多点求值求出每个. 设为,现在我们就是要求,显然可以分治FFT. 具体地,还

CF438E The Child and Binary Tree(生成函数+多项式开根+多项式求逆)

传送门 可以……这很多项式开根模板……而且也完全不知道大佬们怎么把这题的式子推出来的…… 首先,这题需要多项式开根和多项式求逆.多项式求逆看这里->这里,这里讲一讲多项式开根 多项式开方:已知多项式$A$,求多项式$B$满足$A^2\equiv B\pmod{x^n}$(和多项式求逆一样这里需要取模,否则$A$可能会有无数项) 假设我们已经求出$A'^2\equiv B\pmod{x^n}$,考虑如何计算出$A^2\equiv B\pmod{x^{2n}}$ 首先肯定存在$A^2\equiv B