多项式全家桶
目前为止本博客仍是半半半半半成品。
以下是本文参考以及推荐阅读的相关博客
博客都写得很好!没懂是蒟蒻个人问题
点击查看相关博客
OI-wiki 快速傅里叶变换:难得感觉有点抽象。
OI - wiki 拉格朗日插值:配合其他博客食用更佳。
傅里叶变换(FFT)学习笔记:从前置芝士讲起的详细学习笔记。
小学生都能看懂的FFT!!!:比较通俗并且不枯燥的讲解。
快速傅里叶变换(FFT)详解:证明很详细。
多项式初步与傅里叶变换(Fourier Transform) : 清晰但是初看有一丢没看懂,可以康康迭代部分。
多项式 I:拉格朗日插值与快速傅里叶变换:感觉已经算是全家桶了()通过这篇学会了拉插!
从拉插到快速插值求值:超级详细的插值笔记。
概念
-
系数表达转换为点值表达。 -
点值表达转换为系数表达。( 的逆运算 )
拉格朗日插值
考虑构造
首先考虑满足后者,则有:
再考虑前者,则在两边同乘
多项式
注意最后一起算分母的逆元,而不是分别求解。
模版题:luogu P4781
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define LL long long
#define pc(i) putchar(i)
#define fo(i,j,k) for(int i=(j);(i)<=(k);++(i))
#define of(i,j,k) for(int i=(j);(i)>=(k);--(i))
using namespace std;
mt19937 srd(time(0));
cs int inf=0x3f3f3f3f,Mod=998244353,N=2003;
int FL,CH;
template<typename T> bool in(T&a)
{
for(FL=1;!isdigit(CH)&&CH!=EOF;CH=getchar())
if(CH=='-')FL=-1;
for(a=0;isdigit(CH);CH=getchar())
a=a*10+CH-'0';
return a*=FL,CH==EOF?0:1;
}
template<typename T,typename...Args>
int in(T&a,Args&...args){return in(a)+in(args...);}
void wt(int x){if(x<0)x=-x,pc('-');if(x>9)wt(x/10);pc(x%10|48);}
int x[N],y[N],n,k; LL ans;
il int qwq(cs int x,cs int y){return (x-y+Mod)%Mod;}
il int qpow(int b,int p)
{
int r=1;
while(p>0)
{
if(p&1) r=1ll*r*b%Mod;
p>>=1,b=1ll*b*b%Mod;
}
return r;
}
il int inv(cs int x){return qpow(x,Mod-2);}
signed main()
{
in(n,k); fo(i,1,n) in(x[i],y[i]);
fo(i,1,n)
{
int s1=y[i]%Mod,s2=1;
fo(j,1,n) if(i!=j)
s1=1ll*s1*qwq(k,x[j])%Mod,s2=1ll*s2*qwq(x[i],x[j])%Mod;
ans=(ans+1ll*s1*inv(s2)%Mod)%Mod;
}
wt(ans);
return 0;
}
横坐标是连续整数的拉格朗日插值
省流:可以
横坐标为
例题:CF622F The Sum of the k-th Powers
题目大意:求
答案是一个
预处理阶乘和前后缀积。
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define LL long long
#define pc(i) putchar(i)
#define fo(i,j,k) for(int i=(j);(i)<=(k);++(i))
#define of(i,j,k) for(int i=(j);(i)>=(k);--(i))
using namespace std;
mt19937 srd(time(0));
cs int inf=0x3f3f3f3f,Mod=1e9+7,N=1e6+7;
int FL,CH;
template<typename T> bool in(T&a)
{
for(FL=1;!isdigit(CH)&&CH!=EOF;CH=getchar())
if(CH=='-')FL=-1;
for(a=0;isdigit(CH);CH=getchar())
a=a*10+CH-'0';
return a*=FL,CH==EOF?0:1;
}
template<typename T,typename...Args>
int in(T&a,Args&...args){return in(a)+in(args...);}
void wt(int x){if(x<0)x=-x,pc('-');if(x>9)wt(x/10);pc(x%10|48);}
int n,k,ans,fac[N],L[N],R[N],y,num,den;
il int qpow(int b,int p)
{
int re=1;
while(p>0)
{
if(p&1) re=1ll*re*b%Mod;
p>>=1,b=1ll*b*b%Mod;
}
return re;
}
il int inv(cs int x){ return qpow(x,Mod-2); }
signed main()
{
in(n,k),L[0]=R[k+3]=fac[0]=1;
fo(i,1,k+2) L[i]=1ll*L[i-1]*(n-i)%Mod,fac[i]=1ll*fac[i-1]*i%Mod;
of(i,k+2,1) R[i]=1ll*R[i+1]*(n-i)%Mod;
fo(i,1,k+2)
{
y=(y+qpow(i,k))%Mod,num=1ll*L[i-1]*R[i+1]%Mod,
den=1ll*fac[i-1]*((k-i)&1?-1:1)*fac[k+2-i]%Mod;
ans=(ans+1ll*y*num%Mod*inv(den)%Mod)%Mod;
}
wt((ans+Mod)%Mod);
return 0;
}
复数乘法
单位根
快速傅里叶变换
按照下标的奇偶性分类:
设:
则有:
将
将
快速傅里叶逆变换
点值表示法转化为系数表示法。
设有一向量
设
当
上下两式相减可得:
因此,
对于
当
因此,
迭代实现
在原序列中
记为
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define fo(i,j,k) for(int i=(j);(i)<=(k);++(i))
#define of(i,j,k),for(int i=(j);(i)>=(k);--(i))
#define LL long long
using namespace std;
cs int N=3e6+9;
cs double pi=acos(-1);
int FL,CH;
template<typename T>bool in(T&a)
{
for(FL=1;!isdigit(CH)&&CH!=EOF;CH=getchar())
if(CH=='-')FL=-1;
for(a=0;isdigit(CH);CH=getchar())
a=a*10+CH-'0';
return a*=FL,CH==EOF?0:1;
}
template<typename T,typename...Args>
int in(T&a,Args&...args){return in(a)+in(args...);}
struct Complex
{
double x,y;
Complex operator+(const Complex &a) const
{ return {x+a.x,y+a.y}; }
Complex operator-(const Complex &a) const
{ return {x-a.x,y-a.y}; }
Complex operator*(const Complex &a) const
{ return {x*a.x-y*a.y,x*a.y+y*a.x}; }
}A[N],B[N];
int rev[N],bit,tot,n,m;
il void FFT(Complex a[],int inv)
{
fo(i,0,tot-1) if(i<rev[i]) swap(a[i],a[rev[i]]); //求出要迭代的序列
for(int mid=1;mid<tot;mid<<=1)//待合并区间的长度的一半
{
Complex w1=(Complex){cos(pi/mid),inv*sin(pi/mid)};//单位根
for(int i=0;i<tot;i+=mid*2)
{
Complex wk=(Complex){1,0};
for(int j=0;j<mid;++j,wk=wk*w1)//枚举左半部分
{
Complex x=a[i+j],y=wk*a[i+j+mid];
a[i+j]=x+y,a[i+j+mid]=x-y;
}
}
}
}
signed main()
{
in(n,m);
fo(i,0,n) scanf("%lf",&A[i].x);
fo(i,0,m) scanf("%lf",&B[i].x);
while((1<<bit)<n+m+1) ++bit; //bit=ceil(log_2^n)
tot=1<<bit;
fo(i,0,tot-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
FFT(A,1),FFT(B,1);
fo(i,0,tot-1) A[i]=A[i]*B[i];
FFT(A,-1);
fo(i,0,n+m) printf("%d ",(int)(A[i].x/tot+0.5));
return 0;
}
P1919 【模板】A*B Problem 升级版(FFT 快速傅里叶变换)
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define fo(i,j,k) for(int i=(j);(i)<=(k);++(i))
#define of(i,j,k) for(int i=(j);(i)>=(k);--(i))
#define LL long long
using namespace std;
cs int N=3e6+9;
cs double pi=acos(-1);
int FL,CH;
template<typename T>bool in(T&a)
{
for(FL=1;!isdigit(CH)&&CH!=EOF;CH=getchar())
if(CH=='-')FL=-1;
for(a=0;isdigit(CH);CH=getchar())
a=a*10+CH-'0';
return a*=FL,CH==EOF?0:1;
}
template<typename T,typename...Args>
int in(T&a,Args&...args){return in(a)+in(args...);}
struct Complex
{
double x,y;
Complex operator+(cs Complex &a) cs
{ return {x+a.x,y+a.y}; }
Complex operator-(cs Complex &a) cs
{ return {x-a.x,y-a.y}; }
Complex operator*(cs Complex &a) cs
{ return {a.x*x-y*a.y,x*a.y+y*a.x}; }
}A[N],B[N];
char ca[N],cb[N];
int rev[N],bit,tot,n,m,ans[N],id;
il void FFT(Complex a[],cs int inv)
{
fo(i,0,tot-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int mid=1;mid<tot;mid<<=1)
{
Complex w1=(Complex){cos(pi/mid),inv*sin(pi/mid)};
for(int i=0;i<tot;i+=mid*2)
{
Complex wk=(Complex){1,0};
for(int j=0;j<mid;++j,wk=wk*w1)
{
Complex x=a[i+j],y=wk*a[i+j+mid];
a[i+j]=x+y,a[i+j+mid]=x-y;
}
}
}
}
signed main()
{
scanf("%s%s",ca,cb);
n=strlen(ca)-1,m=strlen(cb)-1;
fo(i,0,n) A[i].x=(ca[n-i]^48);
fo(i,0,m) B[i].x=(cb[m-i]^48);
while((1<<bit)<n+m-1) ++bit;
tot=1<<bit;
fo(i,0,tot-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
FFT(A,1),FFT(B,1);
fo(i,0,tot-1) A[i]=A[i]*B[i];
FFT(A,-1);
for(int i=0,x=0;i<tot||x;++i)
x+=A[i].x/tot+0.5,ans[++id]=x%10,x/=10;
while(id>2&&(!ans[id-1])) --id;
of(i,id-1,1) printf("%d",ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】