多项式全家桶(零):前置和目录

       \ \ \ \ \ \ \,终于把多项式差不多弄完了,可以找个机会在退役前把多项式整理封装弄好,也算是留下了一点东西吧(嘿嘿。

       \ \ \ \ \ \ \,这一部分实例的代码是用 std::vectorstd::vector 封装好的,这篇博客先提一下前置:


       \ \ \ \ \ \ \,首先是可能需要用到的定义,都是比较基础的数论知识,不赘述了:

#define Polynomial vector<int>
//封装多项式为 std::vector,方便resize等操作
void print(Polynomial &a,int len){for(int i=0;i<len;i++)printf("%d ",a[i]);}
const int mod=998244353,mod_g=3,img=86583718;
//mod为多项式系数的取模值,mod_g是它的原根,img为在模意义下的虚部,只有多项式三角函数会遇到。
int gcd(int a,int b){return b?gcd(b,a%b):a;}
void exgcd(int a,int b,int &x,int &y){
	if(!b){x=1;y=0;return;}
	exgcd(b,a%b,y,x);y-=x*(a/b);
}
//gcd,exgcd只有在开根的时候会用到
int power(int a,int b)
{int ans=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;}
#define Inv(x) power(x,mod-2)

      &ThinSpace;\ \ \ \ \ \ \,然后是核心的快速数论变换 NTTNTT,相关请看【求多项式卷积的变换】

Polynomial R;
inline int Binary_Rounding(const int &n)
{int len=1;for(;len<n;len<<=1);return len;}
//二进制向上取整,为方便NTT变换准备。
inline int Prepare_Transformation(int n){
  	int L=0,len;for(len=1;len<n;len<<=1)L++;R.clear();R.resize(len);
  	for(int i=0;i<len;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
  	return len;
}
//预处理R数组,准备变换,在每次NTT之前理论都要调用此函数。
void NTT(Polynomial &a,int f){
	int n=a.size();
	for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
  	for(int i=1;i<n;i<<=1)
  	for(int j=0,gn=power(mod_g,(mod-1)/(i<<1));j<n;j+=(i<<1))
  	for(int k=0,g=1,x,y;k<i;k++,g=1ll*g*gn%mod)
	  	x=a[j+k],y=1ll*g*a[i+j+k]%mod,
	  	a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod;
  	if(f==-1){
   		reverse(a.begin()+1,a.end());
    	int inv=Inv(n);
    	for(int i=0;i<n;i++)a[i]=1ll*a[i]*inv%mod;
  	}
}

      &ThinSpace;\ \ \ \ \ \ \,在掌握上面简单知识后,就可以进行多项式的入门了,我差不多按照学习的拓扑序给出下面的目录,也分开记录一下自己的模板:

      &ThinSpace;\ \ \ \ \ \ \,对了,还是建议用 vectorvector 的,用数组的话,到时候对于临时数组的清空问题会让你怀疑人生的!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章