Note_4.1
2019/4/1 奇奇怪怪的笔记
多项式除法
问题描述
给定\(n\)次多项式\(A(x)\)和\(m\)次多项式\(B(x)\)
求:
\]
我们要求\(C(x)\)的次数必须是\(n-m\),\(R(x)\)的次数小于\(m\) ,所以不能简单地用求逆解决
方法
首先我们考虑:
\]
根据\(A=B*C+R\),我们可以得到:
A(\frac{1}{x})=B(\frac{1}{x})*C(\frac{1}{x})+R(\frac{1}{x})\\
x^nA(\frac{1}{x})=x^mB(\frac{1}{x})*x^{n-m}C(\frac{1}{x})+x^nR(\frac{1}{x})\\
x^nA(\frac{1}{x})=x^mB(\frac{1}{x})*x^{n-m}C(\frac{1}{x}) \mod x^{n-m}
\end{equation}
\]
只要求逆算出\(x^{n-m}C(\frac{1}{x})\),翻转就可以得到\(C(x)\)
代码
#include <bits/stdc++.h>
using namespace std;
#define reg register
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int N=1<<18|5,P=998244353,g=3,invg=332748118;
int pos[N];
#define Mul(x,y) (1ll*(x)*(y)%P)
inline int fpow(int x,int m){int r=1;for(;m;m>>=1,x=Mul(x,x))if(m&1)r=Mul(r,x);return r;}
void init(int len)
{
reg int i;
for(i=0;i<len;++i) pos[i]=(pos[i>>1]>>1)|((i&1)*(len>>1));
}
void NTT(int *a,int n,int type)
{
register int i,j,k,w,wn,X,Y;
for(i=0;i<n;++i) if(i<pos[i]) swap(a[i],a[pos[i]]);
for(i=1;i<n;i<<=1)
{
wn=fpow(type>0?g:invg,(P-1)/(i<<1));
for(j=0;j<n;j+=i<<1)for(w=1,k=0;k<i;++k,w=Mul(w,wn))
{
X=a[j+k],Y=Mul(w,a[j+k+i]);
a[j+k]=(X+Y)%P;a[j+k+i]=(X-Y+P)%P;
}
}
reg int invn=fpow(n,P-2);
if(type==-1)for(i=0;i<n;++i)a[i]=Mul(a[i],invn);
}
inline void Dec(int *a,int *b,int *c,int n){for(reg int i=0;i<n;++i)c[i]=(a[i]-b[i]%P+P)%P;}
inline void Pro(int *a,int *b,int *c,int n)
{
static int len,A[N],B[N];
for(len=1;len<(n<<1);len<<=1);
memcpy(A,a,sizeof(int[n]));memcpy(B,b,sizeof(int[n]));
memset(A+n,0,sizeof(int[len-n]));memset(B+n,0,sizeof(int[len-n]));
reg int i;init(len);
NTT(A,len,1);NTT(B,len,1);
for(i=0;i<len;++i) c[i]=Mul(A[i],B[i]);
NTT(c,len,-1);
memset(c+n,0,sizeof(int[len-n]));
}
void _Inv(int *A,int *b,int n)
{
if(n==1){b[0]=fpow(A[0],P-2);return;}
int t=(n+1)>>1;_Inv(A,b,t);
static int len,a[N];
for(len=1;len<(n<<1);len<<=1);
memcpy(a,A,sizeof(int[n]));
memset(a+n,0,sizeof(int[len-n]));memset(b+t,0,sizeof(int[len-t]));
reg int i;init(len);
NTT(a,len,1),NTT(b,len,1);
for(i=0;i<len;++i) b[i]=(Mul(2ll,b[i])-Mul(a[i],Mul(b[i],b[i]))+P)%P;
NTT(b,len,-1);memset(b+n,0,sizeof(int[len-n]));
}
inline void Inv(const int *A, int *b, const int n)
{
static int a[N];
memcpy(a,A,sizeof(int[n]));
_Inv(a,b,n);
}
inline void Div(int *A,int *B,int *c,int *r,int n,int m)
{
static int a[N],b[N],inv_b[N];
memcpy(a,A,sizeof(int[n]));memcpy(b,B,sizeof(int[m]));
reverse(a,a+n),reverse(b,b+m);
int t=n-m+1;
if(t>=m) memset(b+m,0,sizeof(int[t-m]));
Inv(b,inv_b,t);Pro(a,inv_b,c,t);
reverse(c,c+t);reverse(a,a+n),reverse(b,b+m);
Pro(b,c,b,n);Dec(a,b,r,n);
}
int a[N],b[N],c[N],r[N];
int main()
{
reg int i,n=read()+1,m=read()+1;
for(i=0;i<n;++i) a[i]=read();
for(i=0;i<m;++i) b[i]=read();
Div(a,b,c,r,n,m);
for(i=0;i<=n-m;++i) printf("%d ",c[i]);puts("");
for(i=0;i<m-1;++i) printf("%d ",r[i]);
return 0;
}
多项式对数函数
问题描述
给出一个\(n-1\)次的多项式\(A(x)\),求\(B(x)≡\ln A(x) \mod 998244353\)
方法
考虑对方程两边求导:
\]
所以我们只需要:
- 对\(A(x)\)求逆,得到\(A^{-1}(x)\)
- 对\(A(x)\)求导,得到\(A'(x)\)
- 多项式乘法,\(B'(x)=A'(x)*A^{-1}(x)\)
- 对\(B'(x)\)积分,得到\(B(x)\)
怎么求导和积分? 参照人教版高中选修\(2-1\)
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define reg register
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int N=1<<18|5,P=998244353,g=3,invg=332748118;
#define Mul(x,y) (1ll*(x)*(y)%P)
#define ri reg int i
int _[N],pos[N];
int fpow(int x,int m){int r=1;for(;m;m>>=1,x=Mul(x,x))if(m&1)r=Mul(r,x);return r;}
void der(int *a,int *b,int n){for(ri=0;i<n-1;++i) b[i]=Mul(i+1,a[i+1]);b[n-1]=0;}
void inte(int *a,int *b,int n)
{
ri;for(_[1]=i=1;i<n;++i,_[i]=Mul(_[P%i],P-P/i));
for(i=n-1;i;--i)b[i]=Mul(a[i-1],_[i]);b[0]=0;
}
void init(int len)
{
reg int i;
for(i=0;i<len;++i) pos[i]=(pos[i>>1]>>1)|((i&1)*(len>>1));
}
void NTT(int *a,int n,int type)
{
register int i,j,k,w,wn,X,Y;
for(i=0;i<n;++i) if(i<pos[i]) swap(a[i],a[pos[i]]);
for(i=1;i<n;i<<=1)
{
wn=fpow(type>0?g:invg,(P-1)/(i<<1));
for(j=0;j<n;j+=i<<1)for(w=1,k=0;k<i;++k,w=Mul(w,wn))
{
X=a[j+k],Y=Mul(w,a[j+k+i]);
a[j+k]=(X+Y)%P;a[j+k+i]=(X-Y+P)%P;
}
}
reg int invn=fpow(n,P-2);
if(type==-1)for(i=0;i<n;++i)a[i]=Mul(a[i],invn);
}
void Comb(int *a,int *b,int *c,int n)
{
static int A[N],B[N],len;
for(len=1;len<(n<<1);len<<=1);
memcpy(A,a,sizeof(int[n]));memcpy(B,b,sizeof(int[n]));
memset(A+n,0,sizeof(int[len-n]));memset(B+n,0,sizeof(int[len-n]));
reg int i;init(len);NTT(A,len,1);NTT(B,len,1);
for(i=0;i<len;++i) c[i]=Mul(A[i],B[i]);NTT(c,len,-1);
memset(c+n,0,sizeof(int[len-n]));
}
void _I(int *A,int *b,int n)
{
if(n==1) return(void)(b[0]=fpow(A[0],P-2));
int t=(n+1)>>1;_I(A,b,t);
static int a[N],len;
for(len=1;len<(n<<1);len<<=1);
memcpy(a,A,sizeof(int[n]));memset(a+n,0,sizeof(int[n]));
memset(b+t,0,sizeof(int[len-t]));init(len);
reg int i;NTT(a,len,1);NTT(b,len,1);
for(i=0;i<len;++i)b[i]=(Mul(2ll,b[i])-Mul(a[i],Mul(b[i],b[i]))+P)%P;
NTT(b,len,-1);memset(b+n,0,sizeof(int[len-n]));
}
void Inv(int *A,int *b,int n)
{
static int a[N];
memcpy(a,A,sizeof(int[n]));
_I(a,b,n);
}
void ln(int *A,int *B,int n)
{
static int a[N],da[N];
memcpy(a,A,sizeof(int[n]));memcpy(da,A,sizeof(int[n]));
Inv(a,a,n);der(da,da,n);Comb(da,a,B,n);inte(B,B,n);
}
int A[N],B[N],n;
int main()
{
n=read();
reg int i;
for(i=0;i<n;++i) A[i]=read();
ln(A,B,n);
for(i=0;i<n;++i) printf("%d ",B[i]);
return 0;
}
牛顿迭代法
迭代关系式
目标:求方程\(f(x)=0\)的根
假设当前,我们得到的近似值是\(x_n\),要求得它的\(n+1\)次近似值:
过点\((x_n,f(x_n))\)做曲线的切线\(L:y=f(x_n)+f'(x_n)(x-x0)\)
\(L\)于\(x\)轴的交点是\((x_n-\frac{f(x_n)}{f'(x_n)},0)\)
我们定义牛顿迭代公式就是
\[x_{n+1}=x_n-\frac{f(x_n)}{f'(x_n)}
\]
神仙证明:“如果是连续的,并且待求的零点是孤立的,那么在零点周围存在一个区域,只要初始值位于这个邻近区域内,那么牛顿法必定收敛。 并且,如果不为0, 那么牛顿法将具有平方收敛的性能. 粗略的说,这意味着每迭代一次,牛顿法结果的有效数字将增加一倍”
多项式
牛顿迭代在多项式中同样可行。
假设我们要求\(G(F(x))≡0\mod x^n\)
考虑已经求出\(G(F_0(x)) ≡ 0 \mod x^{⌈\frac{n}{2}⌉}\)把\(G(F(x))\)在\(F_0(z)\)处进行泰勒展开
G(F(x))=G(F_0(x))+\frac{G'(F_0(x))}{1!}(F(x)-F_0(x))+\frac{G''(F_0(x))}{2!}(F(x)-F_0(x))^2+...+\frac{G^{(n)}(F_0(x))}{n!}(F(x)-F_0(x))^n+...
\end{equation}
\]
可知,\(F(x)\)和\(F_0(x)\)模\(x^{⌈\frac{n}{2}⌉}\)同余,所以\((F(x)-F_0(x))^2≡0\mod x^n\)
又因为
\]
所以
\]
多项式指数函数
问题描述
给出一个\(n-1\)次的多项式\(A(x)\),求\(B(x)≡e^{A(x)} \mod x^{n}\),\(a_0=0\),然后\(\mod 998244353\)
方法
等同于:
\]
对\(F\)求导
\]
套用牛顿迭代
\begin{split}
B(x)&\leftarrow B_0(x)-\frac{F(B_0(x))}{F'(B_0(x))}\\
&=B_0(x)-(ln(B_0(x))-A(x))B_0(x)\\
&=B_0(x)(-ln(B_0(x))+A(x)+1)
\end{split}
\end{equation}
\]
考虑边界情况,因为本题限定了\(a_0=0\),而\(e^0=1\),所以此时\(b_0=1\)
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define reg register
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int N=1<<18|5,P=998244353,g=3,invg=332748118;
#define Mul(x,y) (1ll*(x)*(y)%P)
#define ri reg int i
int _[N],pos[N];
int fpow(int x,int m){int r=1;for(;m;m>>=1,x=Mul(x,x))if(m&1)r=Mul(r,x);return r;}
void der(int *a,int *b,int n){for(ri=0;i<n-1;++i) b[i]=Mul(i+1,a[i+1]);b[n-1]=0;}
void inte(int *a,int *b,int n)
{
ri;for(_[1]=i=1;i<n;++i,_[i]=Mul(_[P%i],P-P/i));
for(i=n-1;i;--i)b[i]=Mul(a[i-1],_[i]);b[0]=0;
}
void init(int len)
{
reg int i;
for(i=0;i<len;++i) pos[i]=(pos[i>>1]>>1)|((i&1)*(len>>1));
}
void NTT(int *a,int n,int type)
{
register int i,j,k,w,wn,X,Y;
for(i=0;i<n;++i) if(i<pos[i]) swap(a[i],a[pos[i]]);
for(i=1;i<n;i<<=1)
{
wn=fpow(type>0?g:invg,(P-1)/(i<<1));
for(j=0;j<n;j+=i<<1)for(w=1,k=0;k<i;++k,w=Mul(w,wn))
{
X=a[j+k],Y=Mul(w,a[j+k+i]);
a[j+k]=(X+Y)%P;a[j+k+i]=(X-Y+P)%P;
}
}
reg int invn=fpow(n,P-2);
if(type==-1)for(i=0;i<n;++i)a[i]=Mul(a[i],invn);
}
void Comb(int *a,int *b,int *c,int n)
{
static int A[N],B[N],len;
for(len=1;len<(n<<1);len<<=1);
memcpy(A,a,sizeof(int[n]));memcpy(B,b,sizeof(int[n]));
memset(A+n,0,sizeof(int[len-n]));memset(B+n,0,sizeof(int[len-n]));
reg int i;init(len);NTT(A,len,1);NTT(B,len,1);
for(i=0;i<len;++i) c[i]=Mul(A[i],B[i]);NTT(c,len,-1);
memset(c+n,0,sizeof(int[len-n]));
}
void _I(int *A,int *b,int n)
{
if(n==1) return(void)(b[0]=fpow(A[0],P-2));
int t=(n+1)>>1;_I(A,b,t);
static int a[N],len;
for(len=1;len<(n<<1);len<<=1);
memcpy(a,A,sizeof(int[n]));memset(a+n,0,sizeof(int[len-n]));
memset(b+t,0,sizeof(int[len-t]));init(len);
reg int i;NTT(a,len,1);NTT(b,len,1);
for(i=0;i<len;++i)b[i]=(Mul(2ll,b[i])-Mul(a[i],Mul(b[i],b[i]))+P)%P;
NTT(b,len,-1);memset(b+n,0,sizeof(int[len-n]));
}
void Inv(int *A,int *b,int n)
{
static int a[N];
memcpy(a,A,sizeof(int[n]));
_I(a,b,n);
}
void ln(int *A,int *B,int n)
{
static int a[N],da[N];
Inv(A,a,n);der(A,da,n);Comb(da,a,B,n);inte(B,B,n);
}
void _e(int *a,int *b,int n)
{
if(n==1)return(void)(b[0]=1);
int t=(n+1)>>1;_e(a,b,t);
static int xxx[N];
ln(b,xxx,n);reg int i;
for(i=0;i<n;++i)xxx[i]=(-xxx[i]+a[i]+P)%P;
xxx[0]=(xxx[0]+1)%P;
Comb(b,xxx,b,n);
}
void exp(int *A,int *b,int n)
{
static int a[N];
memcpy(a,A,sizeof(int[n]));
_e(a,b,n);
}
int A[N],B[N],n;
int main()
{
n=read();
reg int i;
for(i=0;i<n;++i) A[i]=read();
exp(A,B,n);
for(i=0;i<n;++i) printf("%d ",B[i]);
return 0;
}
多项式快速幂
问题描述
给出一个\(n-1\)次的多项式\(A(x)\),求\(B(x)≡A^k(x) \mod x^{n}\),\(a_0=1\),然后\(\mod 998244353\)
方法
等同于:
\]
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define reg register
const int N=1<<18|5,P=998244353,g=3,invg=332748118;
inline int read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x*10ll+ch-'0')%P;ch=getchar();}
return x*f;
}
#define Mul(x,y) (1ll*(x)*(y)%P)
#define ri reg int i
int _[N],pos[N];
int fpow(int x,int m){int r=1;for(;m;m>>=1,x=Mul(x,x))if(m&1)r=Mul(r,x);return r;}
void der(int *a,int *b,int n){for(ri=0;i<n-1;++i) b[i]=Mul(i+1,a[i+1]);b[n-1]=0;}
void inte(int *a,int *b,int n)
{
ri;for(_[1]=i=1;i<n;++i,_[i]=Mul(_[P%i],P-P/i));
for(i=n-1;i;--i)b[i]=Mul(a[i-1],_[i]);b[0]=0;
}
void init(int len)
{
reg int i;
for(i=0;i<len;++i) pos[i]=(pos[i>>1]>>1)|((i&1)*(len>>1));
}
void NTT(int *a,int n,int type)
{
register int i,j,k,w,wn,X,Y;
for(i=0;i<n;++i) if(i<pos[i]) swap(a[i],a[pos[i]]);
for(i=1;i<n;i<<=1)
{
wn=fpow(type>0?g:invg,(P-1)/(i<<1));
for(j=0;j<n;j+=i<<1)for(w=1,k=0;k<i;++k,w=Mul(w,wn))
{
X=a[j+k],Y=Mul(w,a[j+k+i]);
a[j+k]=(X+Y)%P;a[j+k+i]=(X-Y+P)%P;
}
}
reg int invn=fpow(n,P-2);
if(type==-1)for(i=0;i<n;++i)a[i]=Mul(a[i],invn);
}
void Comb(int *a,int *b,int *c,int n)
{
static int A[N],B[N],len;
for(len=1;len<(n<<1);len<<=1);
memcpy(A,a,sizeof(int[n]));memcpy(B,b,sizeof(int[n]));
memset(A+n,0,sizeof(int[len-n]));memset(B+n,0,sizeof(int[len-n]));
reg int i;init(len);NTT(A,len,1);NTT(B,len,1);
for(i=0;i<len;++i) c[i]=Mul(A[i],B[i]);NTT(c,len,-1);
memset(c+n,0,sizeof(int[len-n]));
}
void _I(int *A,int *b,int n)
{
if(n==1) return(void)(b[0]=fpow(A[0],P-2));
int t=(n+1)>>1;_I(A,b,t);
static int a[N],len;
for(len=1;len<(n<<1);len<<=1);
memcpy(a,A,sizeof(int[n]));memset(a+n,0,sizeof(int[len-n]));
memset(b+t,0,sizeof(int[len-t]));init(len);
reg int i;NTT(a,len,1);NTT(b,len,1);
for(i=0;i<len;++i)b[i]=(Mul(2ll,b[i])-Mul(a[i],Mul(b[i],b[i]))+P)%P;
NTT(b,len,-1);memset(b+n,0,sizeof(int[len-n]));
}
void Inv(int *A,int *b,int n)
{
static int a[N];
memcpy(a,A,sizeof(int[n]));
_I(a,b,n);
}
void ln(int *A,int *B,int n)
{
static int a[N],da[N];
memcpy(a,A,sizeof(int[n]));memcpy(da,A,sizeof(int[n]));
Inv(a,a,n);der(da,da,n);Comb(da,a,B,n);inte(B,B,n);
}
void _e(int *a,int *b,int n)
{
if(n==1)return(void)(b[0]=1);
int t=(n+1)>>1;_e(a,b,t);
static int xxx[N];
ln(b,xxx,n);reg int i;
for(i=0;i<n;++i)xxx[i]=(-xxx[i]+a[i]+P)%P;
xxx[0]=(xxx[0]+1)%P;
Comb(b,xxx,b,n);
}
void exp(int *A,int *b,int n)
{
static int a[N];
memcpy(a,A,sizeof(int[n]));
_e(a,b,n);
}
int A[N],xxx[N],B[N],n,k;
int main()
{
n=read();k=read();
reg int i;
for(i=0;i<n;++i) A[i]=read();
ln(A,xxx,n);
for(i=0;i<n;++i) xxx[i]=Mul(xxx[i],k);
exp(xxx,B,n);
for(i=0;i<n;++i) printf("%d ",B[i]);
return 0;
}
多项式开根
问题描述
给出一个\(n-1\)次的多项式\(A(x)\),求\(B^2(x)≡A(x) \mod x^{n}\),\(a_0=1\),然后\(\mod 998244353\)
方法
首先
\]
考虑牛顿迭代
\begin{split}
B(x)&\leftarrow B_0(x)-\frac{F(B_0(x))}{F'(B_0(x))}\\
&=B_0(x)-\frac{{B^2_0}(x)-A(x)}{2B(x)}\\
&=2^{-1}(B_0(x)+A(x)B^{-1}(x))
\end{split}
\end{equation}
\]
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define reg register
const int N=1<<18|5,P=998244353,g=3,invg=332748118,inv2=499122177;
inline int read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x*10ll+ch-'0')%P;ch=getchar();}
return x*f;
}
#define Mul(x,y) (1ll*(x)*(y)%P)
#define ri reg int i
int _[N],pos[N];
int fpow(int x,int m){int r=1;for(;m;m>>=1,x=Mul(x,x))if(m&1)r=Mul(r,x);return r;}
void der(int *a,int *b,int n){for(ri=0;i<n-1;++i) b[i]=Mul(i+1,a[i+1]);b[n-1]=0;}
void inte(int *a,int *b,int n)
{
ri;for(_[1]=i=1;i<n;++i,_[i]=Mul(_[P%i],P-P/i));
for(i=n-1;i;--i)b[i]=Mul(a[i-1],_[i]);b[0]=0;
}
void init(int len){for(ri=0;i<len;++i) pos[i]=(pos[i>>1]>>1)|((i&1)*(len>>1));}
void NTT(int *a,int n,int type)
{
register int i,j,k,w,wn,X,Y;
for(i=0;i<n;++i) if(i<pos[i]) swap(a[i],a[pos[i]]);
for(i=1;i<n;i<<=1)
{
wn=fpow(type>0?g:invg,(P-1)/(i<<1));
for(j=0;j<n;j+=i<<1)for(w=1,k=0;k<i;++k,w=Mul(w,wn))
{
X=a[j+k],Y=Mul(w,a[j+k+i]);
a[j+k]=(X+Y)%P;a[j+k+i]=(X-Y+P)%P;
}
}
reg int invn=fpow(n,P-2);
if(type==-1)for(i=0;i<n;++i)a[i]=Mul(a[i],invn);
}
void Comb(int *a,int *b,int *c,int n)
{
static int A[N],B[N],len;
for(len=1;len<(n<<1);len<<=1);
memcpy(A,a,sizeof(int[n]));memcpy(B,b,sizeof(int[n]));
memset(A+n,0,sizeof(int[len-n]));memset(B+n,0,sizeof(int[len-n]));
ri;init(len);NTT(A,len,1);NTT(B,len,1);
for(i=0;i<len;++i) c[i]=Mul(A[i],B[i]);NTT(c,len,-1);
memset(c+n,0,sizeof(int[len-n]));
}
void _I(int *A,int *b,int n)
{
if(n==1) return(void)(b[0]=fpow(A[0],P-2));
int t=(n+1)>>1;_I(A,b,t);
static int a[N],len;
for(len=1;len<(n<<1);len<<=1);
memcpy(a,A,sizeof(int[n]));memset(a+n,0,sizeof(int[len-n]));
memset(b+t,0,sizeof(int[len-t]));init(len);
ri;NTT(a,len,1);NTT(b,len,1);
for(i=0;i<len;++i)b[i]=(Mul(2ll,b[i])-Mul(a[i],Mul(b[i],b[i]))+P)%P;
NTT(b,len,-1);memset(b+n,0,sizeof(int[len-n]));
}
void Inv(int *A,int *b,int n)
{
static int a[N];
memcpy(a,A,sizeof(int[n]));
_I(a,b,n);
}
void _S(int *A,int *b,int n)
{
if(n==1) return(void)(b[0]=1);
int t=(n+1)>>1;_S(A,b,t);
static int inv_b[N],a[N],len;
for(len=1;len<(n<<1);len<<=1);
memcpy(a,A,sizeof(int[n]));memset(a+n,0,sizeof(int[len-n]));
Inv(b,inv_b,n);Comb(inv_b,a,a,n);
for(ri=0;i<n;++i) b[i]=Mul((b[i]+a[i])%P,inv2);
memset(b+n,0,sizeof(int[len-n]));
}
void Sqrt(int *A,int *b,int n)
{
static int a[N];
memcpy(a,A,sizeof(int[n]));
memset(b,0,sizeof(int[n]));
_S(a,b,n);
}
int A[N],n,k;
int main()
{
n=read();
reg int i;
for(i=0;i<n;++i) A[i]=read();
Sqrt(A,A,n);for(i=0;i<n;++i) printf("%d ",A[i]);
return 0;
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!
Note_4.1的更多相关文章
- note_4.10
单位根反演 \[ \frac{1}{k}\sum_{i=0}^{k-1}\omega_k^{in}=[k|n] \] 所以 \[ \begin{equation} \begin{split} \sum ...
- Note_4.9
2019/4/9 奇奇怪怪的笔记 关于代码,基本上是现写的,可能连编译都过不了 因为是简单算法场,所以就很不走心了昂,/小纠结 图论相关 最小生成树 prim,kruskal 最小生成树的切割性质 ...
- Note_4.7
2019/4/7 奇奇怪怪的笔记 狄利克雷卷积 \(μ∗1=ϵ\),莫比乌斯反演 \(Id=φ∗1⇒φ=μ∗Id\) \(d=1∗1⇒1=μ∗d\) \(σ=Id∗1⇒Id=μ∗σ\) \(σ=φ∗ ...
- boost::xml——基本操作以及中文乱码解决方案
下面是本人使用boost库的xml部分的基础操作,并且解决对于大家使用boost库读写中文xml内容出现的乱码问题. 1.实现boost库xml基本操作2.解决boost对xml中中文乱码问题3.实现 ...
- Spring MVC(3)Spring MVC 高级应用
一.Spring MVC 的数据转换和格式化 前面的应用,都只是用HandlerAdapter去执行处理器. 处理器和控制器不是一个概念,处理器是在控制器功能的基础上加上了一层包装,有了这层包装,在H ...
- Spring MVC(2)Spring MVC 组件开发
一.控制器接收各类请求参数 代码测试环境: 接收各类参数的控制器--ParamsController package com.ssm.chapter15.controller; @Controller ...
随机推荐
- 【转载】Javascript使用Math.floor方法向下取整
在Javascript的数值运算中,很多时候需要对最后计算结果向下取整,Math.floor是javascript中对计算结果向下取整的函数,它总是将数值向下舍入为最接近的整数.此外Math.ceil ...
- JS中的函数与对象
创建函数的三种方式 1.函数声明 function calSum1(num1, num2) { return num1 + num2; } console.log(calSum1(10, 10)); ...
- JavaScript仿百度图片浏览效果(转载)
转载来源:https://www.jb51.net/article/98030.htm 这是一个非常好的案例,然而jquery的时代正在徐徐关闭. 当你调整浏览器宽高,你会发现它不是自适应的.当你想把 ...
- 【JUC】4.Synchronized与ReentrantLock对比
与synchronized相同,ReentrantLock也是一种互斥锁: synchronized与ReentrantLock的对比: 都是可重入锁 可以再次获取自己的内部锁,即:一个线程获取某对象 ...
- Android笔记(四十) Android中的数据存储——SQLite(二) insert
准备工作: 我们模拟一个注册的页面,先看UI 我们需要创建一个数据库:user,数据库包含表user,user表包含字段id.username.password.mobilephone MainAct ...
- Centos7安装autoconf
一.原因 安装此插件的原因:在初始化MySQL数据库时出现提示FATAL ERROR: please install the following Perl modules before executi ...
- System V共享内存
目录 1. 概述 2. System V共享内存API shmget shmat shmdt shmctl 3. 简单的程序 代码实现 common.h shmcreate.c shmrmid.c s ...
- iptables和lvs
解压密码6Hai7Gf8 路由转发 0是不转发,1是转发 [root@m01 roles]# cat /proc/sys/net/ipv4/ip_forward 0 临时生效 [root@m01 ...
- ealsticsearch历史版本下载
ealsticsearch历史版本下载 https://www.elastic.co/cn/downloads/past-releases#elasticsearch
- 开发一个代码的自动生成器,使用Jfinal4.3+Swagger+Sql
-- 所有表名select column_name 列名, data_type 字段类型, column_comment 字段注释 from information_schema.columns ...