Part1:牛顿迭代
我们有形式幂级数f,t.复合t(f)=0
将t(f)在f0处泰勒展开
然后我们考虑在膜下的意义
Part2:求逆
已知f,求
我们构造t(g)=fg-1,那么我们有
Part3:ln
已知f,求
我们对两边求导
Part4:exp
已知f,求
我们构造t(g)=ln(g)-f
Part5:快速幂
已知f,k,求
1.我们先根据快速幂的思想,发现一个两只log常数巨大的做法
2.
Part6:开根
已知f.求
我们构造t(g)=g^2-f
Part7:除法(差点把他忘了)
求逆即可
就是多项式的综合模板
注:这里的多项式开根常数项要用二次剩余求,但是博主不会二次剩余,于是三岁神仙qy就交给我单次求的BSGS(怒膜一发)
其实就是利用原根性质把x^2化成g^r即可
由于博主用的是vector而且博主代码自带巨大常数,所以就跑的奇慢无比
#include<bits/stdc++.h>
#define ll long long
#define mk(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define cs const
using namespace std;
cs int g=3;
const int N=6e5+10;
const int mod=998244353;
typedef vector<int> poly;
int rev[N],inv[N];
int n,m,len,d,x,k;
poly a;
int mul(int x,int y){return (ll)x*y%mod;}
int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x-y>=0?x-y:x-y+mod;}
int ksm(int x,int y){
ll ans=1;
for (;y;y>>=1,x=mul(x,x)) if (y&1) ans=mul(ans,x);
return ans;
}
int read(){
int f=1,x=0; char c=getchar();
while (c<'0'||c>'9'){if (c=='-')f=-1;c=getchar();}
while (c>='0'&&c<='9'){x=add(mul(x,10),c-'0');c=getchar();}
return x;
}
void init(int x){
len=1,d=0;
while (len<x) {len<<=1;d++;}
for (int i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(d-1));
}
int BSGS(int X,int Y){
int now=floor(sqrt(mod));
int s=ksm(X,now);
map<int,int>mp;
int t=1;
int sum=Y;
for (int i=0;i<now;i++){
mp[sum]=i; sum=mul(sum,X);
}
int s1=1;
for (int i=0;i<mod;i+=now){
s1=mul(s1,s);
if (mp[s1]) return i+now-mp[s1];
}
}
int lalala(int x){
int now=BSGS(g,x);
return ksm(g,now/2);
}
void out(poly a){
for (int i=0;i<a.size();i++) printf("%d ",a[i]);
puts("\n");
}
inline poly NTT(poly a,int t) {
for (int i=0;i<a.size();i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=1;i<a.size();i<<=1) {
int s=(i<<1);
int wn=ksm(g,(mod-1)/s);
if (t==-1) wn=ksm(wn,mod-2);
for (int j=0;j<a.size();j+=s) {
int w=1;
for (int k=j;k<j+i;k++) {
int x=a[k],y=mul(a[k+i],w);
a[k]=add(x,y); a[k+i]=dec(x,y);
w=mul(w,wn);
}
}
}
if (t==-1){
ll w=ksm(a.size(),mod-2);
for (int i=0;i<a.size();i++) a[i]=mul(a[i],w);
}
return a;
}
inline poly get_down(poly a){
for (int i=0;i<a.size()-1;i++) a[i]=mul(a[i+1],i+1);
a.pop_back();
return a;
}
inline poly get_up(poly a){
a.push_back(0);
for (int i=a.size()-1;i>0;i--) a[i]=mul(a[i-1],inv[i]);
a[0]=0;
return a;
}
inline poly operator +(poly a,poly b){
a.resize(max(a.size(),b.size()));
b.resize(max(a.size(),b.size()));
for (int i=0;i<a.size();i++) a[i]=add(a[i],b[i]);
return a;
}
inline poly operator -(poly a,poly b){
a.resize(max(a.size(),b.size()));
b.resize(max(a.size(),b.size()));
for (int i=0;i<a.size();i++) a[i]=dec(a[i],b[i]);
return a;
}
inline poly operator *(poly a,int x){
for (int i=0;i<a.size();i++) a[i]=mul(a[i],x);
return a;
}
inline poly operator *(poly a,poly b){
int n=a.size(),m=b.size();
init(n+m-1);
a.resize(len);
b.resize(len);
a=NTT(a,1); b=NTT(b,1);
for (int i=0;i<a.size();i++) a[i]=mul(a[i],b[i]);
a=NTT(a,-1);
a.resize(n+m-1);
return a;
}
inline poly get_inv(poly a){
poly b,d;
b.pb(ksm(a[0],mod-2)); d.pb(a[0]);
int now=1;
while (now<a.size()) {
now<<=1;
poly c=b;
c=c*c;
for (int i=(now>>1);i<now&&i<a.size();i++) d.pb(a[i]);
c=c*d;c.resize(now);
b=b*2; b=b-c;
}
b.resize(a.size());
return b;
}
inline poly ln(poly a){poly c=get_up(get_inv(a)*get_down(a));c.resize(a.size());return c;}
inline poly exp(poly a){
poly b,d;
b.pb(1); d.pb(a[0]);
int now=1;
while (now<a.size()){
now<<=1;
for (int i=(now>>1);i<now&&i<a.size();i++) d.pb(a[i]);
poly c=b;
c.resize(now);
c=ln(c)-d;
for (int i=0;i<c.size();i++) c[i]=(mod-c[i])%mod;
c[0]=add(c[0],1);
b=b*c; b.resize(now);
}
b.resize(a.size());
return b;
}
inline poly ksm(poly a,int k){return exp(ln(a)*k);}
inline poly Sqrt(poly a){
poly b,d;
b.pb(lalala(a[0])); d.pb(a[0]);
b[0]=min(b[0],mod-b[0]);
int now=1;
while (now<a.size()){
now<<=1; poly c=b;
for (int i=(now>>1);i<now&&i<a.size();i++) d.pb(a[i]);
c.resize(now);
c=get_inv(c);
c=c*d;c.resize(now);
b=b+c;
for (int i=0;i<now;i++) b[i]=mul(b[i],inv[2]);
}
b.resize(a.size());
return b;
}
int main(){
// freopen("da.in","r",stdin);
// freopen("da.out","w",stdout);
inv[0]=inv[1]=1;
for (int i=2;i<N;i++) inv[i]=mul(inv[mod%i],(mod-mod/i));
scanf("%d",&n); k=read();
for (int i=0;i<=n;i++) {
scanf("%d",&x); a.pb(x);
}
poly b=a;
a=Sqrt(a);a=get_inv(a);a=get_up(a);
a=exp(a); b[0]=2;
a=b-a;a=ln(a);a[0]=1;
a=ksm(a,k);a=get_down(a);
a.resize(n);
out(a);
// fclose(stdin);
// fclose(stdout);
}