多项式全(?)家桶
之前写的板子太丑了,封装的也不好,重新贴一遍吧。
主函数是多项式取余那题的,不关键。
代码
点击查看代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxn 400010
#define ll long long
#define mod 998244353
using namespace std;
const ll g=3;
ll qpow(ll x,int p){
ll base,ans;
for(base=x,ans=1;p;p>>=1,base=base*base%mod){
if(p&1) ans=ans*base%mod;
}
return ans;
}
ll inv(ll x){
return qpow(x,mod-2);
}
ll sqr(ll x){
return 1;
}
void read(ll &x){
x=0;
char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
}
void write(ll x){
char s[30];
int c=0;
if(!x){
printf("0");
return;
}
while(x){
s[++c]=x%10+'0';
x/=10;
}
for(int i=c;i>=1;--i) putchar(s[i]);
}
namespace NTT{
static ll A[maxn],B[maxn],w[maxn];
int pos[maxn];
int init(int n){
int lg=0;
while((1<<lg)<n) ++lg;
for(int i=1;i<(1<<lg);++i) pos[i]=(pos[i>>1]>>1)|((1&i)<<(lg-1));
return lg;
}
void ntt(ll *L,int N,int type){
for(int i=0;i<N;++i){
if(i<pos[i]) swap(L[i],L[pos[i]]);
}
w[0]=1;w[1]=qpow(g,(mod-1)/N);
if(type<0) w[1]=inv(w[1]);
for(int i=2;i<N;++i) w[i]=w[i-1]*w[1]%mod;
for(int d=1,t=N>>1;d<N;d<<=1,t>>=1){
for(int i=0;i<N;i+=(d<<1)){
for(int j=i;j<i+d;++j){
ll tmp=w[(j-i)*t]*L[j+d]%mod;
L[j+d]=(L[j]-tmp+mod)%mod;
L[j]=(L[j]+tmp)%mod;
}
}
}
}
void multi(ll *L1,int n,ll *L2,int m,ll *L3){
int lg=init(n+m-1),len=1<<lg;
for(int i=0;i<len;++i) A[i]=i<n?L1[i]:0;
for(int i=0;i<len;++i) B[i]=i<m?L2[i]:0;
ntt(A,len,1);ntt(B,len,1);
for(int i=0;i<len;++i) L3[i]=A[i]*B[i]%mod;
ntt(L3,len,-1);
ll t=inv(len);
for(int i=0;i<len;++i) L3[i]=L3[i]*t%mod;
}
};
namespace poly{
void Diff(ll *L,int n){//求导
for(int i=0;i<n;++i) L[i]=L[i+1]*(i+1)%mod;
L[n-1]=0;
}
void Int(ll *L,int n){//积分
for(int i=n;i>0;--i) L[i]=L[i-1]*inv(i)%mod;
L[0]=0;
}
void Rev(ll *L,int n){
for(int i=0;i<n-i-1;++i) swap(L[i],L[n-i-1]);
}
void Inv(ll *L,int n){//多项式乘法逆
static ll A[maxn],B[maxn];
int lg=NTT::init(n),len;
for(int i=0;i<(1<<lg+1);++i) A[i]=B[i]=0;
B[0]=inv(L[0]);
for(int i=0,len=1;i<=lg;++i,len<<=1){
for(int j=0;j<(len<<1);++j) A[j]=j<len?L[j]:0;
NTT::init(len<<1);
NTT::ntt(A,len<<1,1);NTT::ntt(B,len<<1,1);
for(int j=0;j<(len<<1);++j) B[j]=(mod+2-A[j]*B[j]%mod)%mod*B[j]%mod;
NTT::ntt(B,len<<1,-1);
for(int j=0;j<len;++j) B[j]=B[j]*inv(len<<1)%mod;
for(int j=len;j<(len<<1);++j) B[j]=0;
}
for(int i=0;i<(1<<lg);++i) L[i]=i<n?B[i]:0;
}
void Ln(ll *L,int n){//多项式对数函数
static ll A[maxn],B[maxn],C[maxn];
int lg=NTT::init(n);
for(int i=0;i<(1<<lg+1);++i) A[i]=B[i]=C[i]=0;
for(int i=0;i<n;++i) A[i]=L[i];
Diff(A,n);
for(int i=0;i<n;++i) B[i]=L[i];
Inv(B,n);
NTT::multi(A,n-1,B,n,C);
Int(C,2*n);
for(int i=0;i<n;++i) L[i]=C[i];
}
void Exp(ll *L,int n){//多项式指数函数
static ll A[maxn],B[maxn],ln[maxn];
int lg=NTT::init(n),len;
for(int i=0;i<(1<<lg+1);++i) A[i]=B[i]=ln[i]=0;
B[0]=1;
for(int i=0,len=1;i<=lg;++i,len<<=1){
for(int j=0;j<(len<<1);++j) A[j]=j<len?L[j]:0;
for(int j=0;j<(len<<1);++j) ln[j]=j<len?B[j]:0;
Ln(ln,len);
NTT::init(len<<1);
NTT::ntt(B,len<<1,1);
NTT::ntt(ln,len<<1,1);
NTT::ntt(A,len<<1,1);
for(int j=0;j<(len<<1);++j) B[j]=(1-ln[j]+A[j]+mod)%mod*B[j]%mod;
NTT::ntt(B,len<<1,-1);
for(int j=0;j<(len<<1);++j) B[j]=B[j]*inv(len<<1)%mod;
}
for(int i=0;i<(1<<lg);++i) L[i]=i<n?B[i]:0;
}
void Cos(ll *L,int n){//多项式三角函数cos
static ll A[maxn],B[maxn];
ll j=qpow(g,mod-1>>2);
for(int i=0;i<n;++i) A[i]=B[i]=0;
for(int i=0;i<n;++i) A[i]=L[i]*j%mod;
Exp(A,n);
for(int i=0;i<n;++i) B[i]=A[i];
Inv(B,n);
ll t=inv(2);
for(int i=0;i<n;++i) L[i]=(A[i]+B[i])%mod*t%mod;
}
void Sin(ll *L,int n){//多项式三角函数sin
static ll A[maxn],B[maxn];
ll j=qpow(g,mod-1>>2);
for(int i=0;i<n;++i) A[i]=B[i]=0;
for(int i=0;i<n;++i) A[i]=L[i]*j%mod;
Exp(A,n);
for(int i=0;i<n;++i) B[i]=A[i];
Inv(B,n);
ll t=inv(2*j%mod);
for(int i=0;i<n;++i) L[i]=(A[i]-B[i]+mod)%mod*t%mod;
}
void Kasumi(ll *L,int n,int k){//多项式幂函数
static ll A[maxn];
for(int i=0;i<n;++i) A[i]=L[i];
Ln(A,n);
for(int i=0;i<n;++i) A[i]=A[i]*k%mod;
Exp(A,n);
for(int i=0;i<n;++i) L[i]=A[i];
}
void Sqrt(ll *L,int n){//多项式开根(默认常数项为1,否则sqr函数要写BSGS)
static ll A[maxn],B[maxn],iB[maxn];
int lg=NTT::init(n),len;
for(int i=0;i<(1<<lg+1);++i) A[i]=B[i]=iB[i]=0;
B[0]=sqr(A[0]);
for(int i=0,len=1;i<=lg;++i,len<<=1){
for(int j=0;j<(len<<1);++j) A[j]=j<len?L[j]:0;
for(int j=0;j<(len<<1);++j) iB[j]=j<len?B[j]:0;
Inv(iB,len);
NTT::init(len<<1);
NTT::ntt(A,len<<1,1);
NTT::ntt(B,len<<1,1);
NTT::ntt(iB,len<<1,1);
ll t=inv(2);
for(int j=0;j<(len<<1);++j) B[j]=(B[j]+A[j]*iB[j]%mod)*t%mod;
NTT::ntt(B,len<<1,-1);
t=inv(len<<1);
for(int j=0;j<(len<<1);++j) B[j]=B[j]*t%mod;
}
for(int i=0;i<n;++i) L[i]=B[i];
}
void Mod(ll *L1,int n,ll *L2,int m,ll *L3,ll *L4){//L1对L2取模,商存到L3中,余数在L4中
static ll Q[maxn],R[maxn],F[maxn],G[maxn];
for(int i=0;i<n;++i) F[i]=L1[i];
for(int i=0;i<m;++i) G[i]=L2[i];
Rev(F,n),Rev(G,m);
Inv(G,n-m+1);
NTT::multi(G,n-m+1,F,n-m+1,Q);
Rev(Q,n-m+1);
for(int i=0;i<n-m+1;++i) L3[i]=Q[i];//计算商式
for(int i=0;i<n;++i) F[i]=L1[i];
for(int i=0;i<n;++i) G[i]=i<m?L2[i]:0;
for(int i=n-m+1;i<n;++i) Q[i]=0;
NTT::multi(G,m,Q,n-m+1,R);
for(int i=0;i<m;++i) R[i]=(F[i]-R[i]+mod)%mod;
for(int i=0;i<m;++i) L4[i]=R[i];//计算余式
}
};
ll a[maxn],b[maxn],c[maxn],d[maxn];
int main(){
int i,n,k,m;
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
scanf("%d%d",&n,&m);
m++,n++;
for(i=0;i<n;++i) read(a[i]);
for(i=0;i<m;++i) read(b[i]);
poly::Mod(a,n,b,m,c,d);
for(i=0;i<n-m+1;++i) write(c[i]),putchar(' ');
putchar('\n');
for(i=0;i<m-1;++i) write(d[i]),putchar(' ');
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】