pp_orange的多项式模板
namespace poly{
const int de = 1;
const int intsz = sizeof(int);
int getN(int n){
int N = 1;
while(N<=n)N<<=1;
return N;
}
namespace polyNTT{
int r[MAX];
int nwsz = -1;
void initR(int N,int lim){
if(nwsz==lim)return ;
nwsz = lim;
rep(i,1,N)r[i] = (r[i>>1]>>1)|((i&1)<<(lim-1));
return ;
}
const int G = 3;
const int Gi = pw(G,mod-2);
int x,y;
void NTT(int *a,int N,int tp){
//1:G, -1:Gi
//need init R
if(de)assert(__builtin_ctz(N)==nwsz);
const int g = tp==1?G:Gi;
int omg;
ll w;
rep(i,0,N)if(r[i]<i)swap(a[i],a[r[i]]);
for(int mid=1;mid<N;(mid<<=1)){
omg = pw(g,(mod-1)/(mid<<1));
for(int i=0,len=(mid<<1);i<N;i+=len){
w = 1;
for(int j=i;j<i+mid;++j,w=w*omg%mod){
x = a[j];
y = a[j+mid]*w%mod;
a[j] = (x+y)%mod;
a[j+mid] = (x-y+mod)%mod;
}
}
}
return ;
}
}using polyNTT::NTT,polyNTT::initR;
namespace polyMul{
int tmp[MAX];
void Mul(int *a,int n,int *b,int m){
//Mul(rlt,n,b,m) , won't destroy b
//a^n and b^m
memcpy(tmp,b,intsz*(m+1));
int lim = 0;
int N = 1;
while(N<=n+m){
N <<= 1;
lim++;
}
initR(N,lim);
NTT(a,N,1);
NTT(b,N,1);
ll Ni = pw(N,mod-2);
rep(i,0,N)a[i] = (ll)a[i]*b[i]%mod*Ni%mod;
NTT(a,N,-1);
memcpy(b,tmp,intsz*(m+1));
memset(b+m+1,0,intsz*(N-(m+1)));
return ;
}
}using polyMul::Mul;
namespace polyInv{
int f[MAX];
void Inv(int *b,int *a,int n){
//Inv(output,input,n) mod x^n , won't destroy a
int N = 1;
int lim = 0;
b[0] = pw(a[0],mod-2);b[1] = 0;
while(N<n){
lim++;
N <<= 1;
initR(N,lim);
memset(b+N,0,intsz*N);
memcpy(f,a,intsz*N);
memset(f+N,0,intsz*N);
initR(N<<1,lim+1);
NTT(b,N*2,1);
NTT(f,N*2,1);
rep(i,0,N*2)f[i] = b[i]*(2-(ll)b[i]*f[i]%mod+mod)%mod;
NTT(f,N*2,-1);
ll Ni = pw(N*2,mod-2);
rep(i,0,N)b[i] = f[i]*Ni%mod;
memset(b+N,0,intsz*N);
}
memset(b+n,0,intsz*(N-n));
}
}using polyInv::Inv;
namespace polySqrt{
int gi[MAX];
int f[MAX];
const int inv2 = pw(2,mod-2);
void Sqrt(int *b,int *a,int n){
//Sqrt(output,input,n) , mod x^n
int N = 1;
int lim = 0;
if(de)assert(a[0]==1);
b[0] = 1;b[1] = 0;
while(N<n){
lim++;
N <<= 1;
memset(b+N,0,intsz*N);
Inv(gi,b,N);
memset(gi+N,0,intsz*N);
memcpy(f,a,intsz*N);
memset(f+N,0,intsz*N);
initR(N*2,lim+1);
NTT(gi,N*2,1);
NTT(f,N*2,1);
NTT(b,N*2,1);
ll Ni = pw(N*2,mod-2);
rep(i,0,N*2)b[i] = ((ll)f[i]*gi[i]%mod+b[i])*inv2%mod*Ni%mod;
NTT(b,N*2,-1);
memset(b+N,0,intsz*N);
}
memset(b+n,0,intsz*(N-n));
return ;
}
}using polySqrt::Sqrt;
void Dev(int *a,int n){
//get Dev [ 0 , n )
rep(i,0,n-1)a[i] = ((ll)a[i+1]*(i+1))%mod;
a[n-1] = 0;
return ;
}
namespace polyInter{
int inv[MAX] = {0,1};
int invsz = 1;
void initInv(int sz){
if(sz<=invsz)return ;
repp(i,2,sz)inv[i] = (mod-(ll)inv[mod%i]*(mod/i)%mod);
invsz = sz;
}
void Inter(int *a,int n){
//get Inter [ 0 , n )
initInv(n);
per(i,n,1)a[i] = ((ll)a[i-1]*inv[i])%mod;
a[0] = 0;
return ;
}
}using polyInter::Inter;
namespace polyLn{
int tmp[MAX];
void Ln(int *b,int *a,int n){
//Ln(out,in,n) , won't destroy a , mod x^n
memcpy(tmp,a,intsz*n);
int N = getN(n-1)*2;
if(de)assert(a[0]==1);
memcpy(b,a,intsz*N);
Inv(a,b,n);
Dev(b,n);
initR(N,__builtin_ctz(N));
NTT(a,N,1);
NTT(b,N,1);
ll Ni = pw(N,mod-2);
rep(i,0,N)b[i] = ((ll)a[i]*b[i]%mod*Ni)%mod;
NTT(b,N,-1);
memset(b+n,0,intsz*(N-n));
Inter(b,n);
memcpy(a,tmp,intsz*n);
memset(a+n,0,intsz*(N-n));
return ;
}
}using polyLn::Ln;
namespace polyExp{
int c[MAX];
int d[MAX];
void Exp(int *b,int *a,int n){
//Exp(out,in,n) , won't destroy a
// mod x^n
if(de)assert(a[0]==0);
int N = 1,lim = 0;
b[0] = 1,b[1] = 0;
while(N<n){
N <<= 1;
lim++;
memset(b+N,0,intsz*N);
Ln(c,b,N);
memcpy(d,a,intsz*N);
memset(d+N,0,intsz*N);
initR(N*2,lim+1);
NTT(b,N*2,1);
NTT(c,N*2,1);
NTT(d,N*2,1);
ll Ni = pw(N*2,mod-2);
rep(i,0,N*2)b[i] = (1ll-c[i]+d[i]+mod)%mod*b[i]%mod*Ni%mod;
NTT(b,N*2,-1);
memset(b+N,0,intsz*N);
}
memset(b+n,0,intsz*(N-n));
return ;
}
}using polyExp::Exp;
namespace polyPow{
//暂不支持多测
int tmp[MAX];
int c[MAX];
void Pow(int *b,int *a,int n,ll d){
if(d==0){
memset(b,0,intsz*n);
b[0] = 1;
return ;
}
//Pow(rlt&input,len,times); mod x^len
if(de)assert(a[0]==1);
Ln(tmp,a,n);
rep(i,0,n)tmp[i] = (tmp[i]*d)%mod;
Exp(b,tmp,n);
return ;
}
void exPow(int *b,int *a,int n,ll d,ll d2 = -1){
//exPow(rlt&input,len,times%mod,times%(mod-1)); mod x^len
if(d2==-1)d2=d;
if(d==0){
memset(b,0,intsz*n);
b[0] = pw(a[0],d2);
return ;
}
int cnt = 0;
rep(i,0,n){
if(a[i]==0)cnt++;
else break;
}
ll m = cnt*d;
if(m>=n){
memset(b,0,intsz*n);
return ;
}
ll f0 = a[cnt];
ll if0 = pw(f0,mod-2);
memcpy(c,a+cnt,intsz*(n-m));
rep(i,0,n-m)c[i] = (c[i]*if0)%mod;
Pow(b+m,c,n-m,d);
memset(b,0,intsz*m);
f0 = pw(f0,d2);
rep(i,m,n)b[i] = (b[i]*f0)%mod;
return ;
}
}using polyPow::Pow,polyPow::exPow;
void Rev(int *a,int n){
reverse(a,a+n+1);
return ;
}
namespace polyDiv{
int gi[MAX];
int tmpg[MAX];
void Div(int *q,int *r,int *f,int n,int *g,int m){
//f(n) = q(n-m)*g(m)+r(m-1)
// memset(gi,0,sizeof(gi));
memset(tmpg,0,intsz*getN(n));
assert(m<=n);
Rev(f,n);Rev(g,m);
int sz = n-m+1;
memcpy(tmpg,g,intsz*sz);
Inv(gi,tmpg,sz);
Mul(gi,sz-1,f,n);
memcpy(q,gi,intsz*sz);
Rev(f,n);Rev(g,m);Rev(q,n-m);
//memset(q)...
memcpy(tmpg,q,intsz*sz);
Mul(tmpg,n-m,g,m);
rep(i,0,m)r[i] = (f[i]-tmpg[i]+mod)%mod;
return ;
}
}using polyDiv::Div;
namespace polyMod{
int tmp[MAX];
void Mod(int *r,int *f,int n,int *g,int m){
// memset(tmp,0,sizeof(tmp));
Div(tmp,r,f,n,g,m);
return ;
}
}using polyMod::Mod;
namespace polyBM{
//暂不支持多测
int v[MAX];
int tmp[MAX];
void BM(int *r,int *f,int k,int n){
r[0] = 1;
int N = getN((k-1)*2);
int lim = __builtin_ctz(N);
ll Ni = pw(N,mod-2);
v[1] = 1;
initR(N,lim);
for(;n;n>>=1){
if(n&1){
memcpy(tmp,r,intsz*N);
Mul(tmp,k-1,v,k-1);
Mod(r,tmp,N-1,f,k);
}
if(n==1)return;
memcpy(tmp,v,intsz*N);
initR(N,lim);
NTT(tmp,N,1);
rep(i,0,N)tmp[i] = ((ll)tmp[i]*tmp[i]%mod*Ni)%mod;
NTT(tmp,N,-1);
Mod(v,tmp,N,f,k);
}
return ;
}
}using polyBM::BM;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~