[关闭]
@jason-fan 2021-04-06T10:38:06.000000Z 字数 6189 阅读 146

CODE

  1. #pragma GCC optimize(2)
  2. #pragma GCC optimize(3)
  3. #pragma GCC optimize(3,"Ofast","inline")
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <cstring>
  7. #include <vector>
  8. #include <cstdio>
  9. #include <cmath>
  10. #include "../debuger.h"
  11. using namespace std;
  12. template<typename _Tp>
  13. inline void red(_Tp &x) {
  14. x=0;bool fg=0;char ch=getchar();
  15. while(ch<'0'||ch>'9') {if(ch=='-') fg^=1;ch=getchar();}
  16. while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(_Tp)(ch^48),ch=getchar();
  17. if(fg) x=-x;
  18. }
  19. typedef long long ll;
  20. /*-------------------------------BEGIN POLY FAMILY BUCKET---------------------------------------*/
  21. #define clr(f,n) memset(f,0,sizeof(long long)*(n))
  22. #define cpy(f,g,n) memcpy(f,g,sizeof(long long)*(n))
  23. #define Outarr(x,n) cerr<<#x<<" : "; for(int i=0;i<n;++i) cerr<<x[i]<<" ";cout<<endl;
  24. #define outarr(x,n) for(int i=0;i<n;++i) printf("%lld%c",x[i],(i==n-1)?'\n':' ');
  25. #define MOD(x) ((x)<mod?(x):((x)%mod))
  26. namespace poly {
  27. const int mod = 998244353;
  28. const int N = (1<<19);
  29. const int _G = 3;
  30. const int _iG = 332748118;
  31. const int inv2 = 499122177;
  32. ll fpow(ll a,ll b,ll p) {
  33. ll r=1;
  34. for(;b;a=a*a%p,b>>=1) if(b&1) r=r*a%p;
  35. return r;
  36. }
  37. int rev[N],rev_n;
  38. void prerev(int n) {
  39. if(n==rev_n) return;
  40. rev_n=n;
  41. for(int i=0;i<n;++i) rev[i]=(rev[i>>1]>>1)|((i&1)?(n>>1):0);
  42. }
  43. // NTT : fg=1 DFT fg=-1 IDFT
  44. template<typename IT>
  45. void NTT(IT f,int n,int fg) {
  46. prerev(n);
  47. for(int i=0;i<n;++i) if(i<rev[i]) swap(f[i],f[rev[i]]);
  48. for(int h=2;h<=n;h<<=1) {
  49. ll Dt=fpow((fg==1)?_G:_iG,(mod-1)/h,mod),w;
  50. int len=h>>1;
  51. for(int j=0;j<n;j+=h) {
  52. w=1;
  53. for(int k=j;k<j+len;++k) {
  54. ll tmp=MOD(f[k+len]*w);
  55. f[k+len]=f[k]-tmp; (f[k+len]<0)&&(f[k+len]+=mod);
  56. f[k]=f[k]+tmp; (f[k]>=mod)&&(f[k]-=mod);
  57. w=MOD(w*Dt);
  58. }
  59. }
  60. }
  61. if(fg==-1) {
  62. ll invn=fpow(n,mod-2,mod);
  63. for(int i=0;i<n;++i) f[i]=MOD(f[i]*invn);
  64. }
  65. }
  66. // f(x) = f*g(x) n = def f ; m = def g ; len = 最终长度(保留几位)
  67. void p_mul(ll f[],ll g[],int n,int m,int len) {
  68. static ll a[N],b[N];
  69. int nn=1<<(int)ceil(log2(n+m-1));
  70. clr(a,nn); clr(b,nn); cpy(a,f,n); cpy(b,g,m);
  71. NTT(a,nn,1); NTT(b,nn,1);
  72. for(int i=0;i<nn;++i) a[i]=MOD(a[i]*b[i]);
  73. NTT(a,nn,-1);
  74. for(int i=0;i<len;++i) f[i]=a[i];
  75. }
  76. // f(x) = g^-1(x) f(x) 为 g(x) 模 x^n 意义下的逆
  77. void p_inv(ll g[],int n,ll f[]) {
  78. static ll sav[N];
  79. int nn=1<<(int)ceil(log2(n));
  80. clr(f,n*2);
  81. f[0]=fpow(g[0],mod-2,mod);
  82. for(int h=2;h<=nn;h<<=1) {
  83. cpy(sav,g,h); clr(sav+h,h);
  84. NTT(sav,h<<1,1); NTT(f,h<<1,1);
  85. for(int i=0;i<(h<<1);++i) {
  86. f[i]=f[i]*(2ll-f[i]*sav[i]%mod+mod)%mod;
  87. }
  88. NTT(f,h<<1,-1); clr(f+h,h);
  89. }
  90. clr(f+n,nn*2-n);
  91. }
  92. // f^2(x) = g(x) f(x) 为 g(x) 模 x^n 意义下的开方
  93. void p_sqrt(ll g[],int n,ll f[]) {
  94. static ll sav[N],r[N];
  95. int nn=1<<(int)ceil(log2(n));
  96. clr(f,n*2); f[0]=1; // g[0] should be 1 otherwise
  97. for(int h=2;h<=nn;h<<=1) {
  98. cpy(sav,g,h); clr(sav+h,h); p_inv(f,h,r);
  99. NTT(sav,h<<1,1); NTT(r,h<<1,1);
  100. for(int i=0;i<(h<<1);++i) sav[i]=MOD(sav[i]*r[i]);
  101. NTT(sav,h<<1,-1);
  102. for(int i=0;i<h;++i) f[i]=MOD((f[i]+sav[i])*inv2);
  103. clr(f+h,h);
  104. }
  105. clr(f+n,nn*2-n);
  106. }
  107. // f(x) = g(x) * q(x) + r(x) : q(x) 为商 r(x) 为余数
  108. void p_div(ll f[],ll g[],int n,int m,ll q[],ll r[]) {
  109. static ll sav1[N],sav2[N];
  110. int nn; for(nn=1;nn<n-m+1;nn<<=1);
  111. clr(sav1,nn); clr(sav2,nn); cpy(sav1,f,n); cpy(sav2,g,m);
  112. reverse(sav1,sav1+n); reverse(sav2,sav2+m);
  113. p_inv(sav2,n-m+1,q); p_mul(q,sav1,n-m+1,n,n-m+1);
  114. reverse(q,q+n-m+1); cpy(r,g,m);
  115. p_mul(r,q,m,n-m+1,m-1);
  116. for(int i=0;i<m-1;++i) r[i]=MOD(f[i]-r[i]+mod);
  117. }
  118. // 预处理乘法逆元
  119. ll inv[N],fac[N],ifac[N];
  120. void Initinv(int n) {
  121. inv[0]=inv[1]=1;
  122. fac[0]=fac[1]=ifac[0]=ifac[1]=1;
  123. for(int i=2;i<n;++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
  124. for(int i=2;i<n;++i) fac[i]=fac[i-1]*i%mod;
  125. for(int i=2;i<n;++i) ifac[i]=ifac[i-1]*inv[i]%mod;
  126. }
  127. // 对 f(x) 进行积分 Initinv() first
  128. void p_int(ll f[],int n) {
  129. for(int i=n-1;i;--i) f[i]=MOD(f[i-1]*inv[i]);
  130. f[0]=0;
  131. }
  132. // 对 f(x) 进行求导
  133. void p_der(ll f[],int n) {
  134. for(int i=1;i<n;++i) f[i-1]=MOD(f[i]*i);
  135. f[n-1]=0;
  136. }
  137. // f(x) <- ln f(x) f[0] should be 1
  138. void p_ln(ll f[],int n) {
  139. static ll g[N];
  140. p_inv(f,n,g); p_der(f,n);
  141. p_mul(f,g,n,n,n+n);
  142. p_int(f,n);
  143. }
  144. // f(x) <- exp f(x) (倍增版) f[0] should be 0
  145. void p_exp(ll f[],int n) {
  146. static ll g[N],sav[N];
  147. clr(g,n*2); clr(sav,n*2); g[0]=1;
  148. for(int h=2;h<=n;h<<=1) {
  149. cpy(sav,g,h); p_ln(sav,h);
  150. for(int i=0;i<h;++i) sav[i]=MOD(f[i]-sav[i]+mod);
  151. sav[0]=MOD(sav[0]+1);
  152. p_mul(g,sav,h,h,h);
  153. }
  154. cpy(f,g,n);
  155. }
  156. /*
  157. void _p_exp(ll f[],ll g[],int l,int r) {
  158. static ll A[N],B[N];
  159. if(r-l==1) {if(l>0) f[l]=MOD(f[l]*fpow(l,mod-2,mod));return ;}
  160. int mid=(l+r)>>1,len=mid-l;
  161. _p_exp(f,g,l,mid);
  162. cpy(A,f+l,len); clr(A+len,len); cpy(B,g,len<<1);
  163. p_mul(A,B,len<<1,len<<1,len<<1);
  164. for(int i=mid;i<r;++i) f[i]=MOD(f[i]+A[i-l]);
  165. _p_exp(f,g,mid,r);
  166. }
  167. // f(x) <- exp f(x) (分治 FFT 版) f[0] should be 0
  168. void p_exp(ll f[],int n) {
  169. static ll g[N];
  170. cpy(g,f,n); clr(f,n); f[0]=1;
  171. for(int i=0;i<n;++i) g[i]=MOD(g[i]*i);
  172. _p_exp(f,g,0,n);
  173. }
  174. */
  175. // f(x) <- f^k(x) f(x) 模 x^n 意义下的 k 次
  176. void p_pow(ll f[],int n,ll k) {
  177. p_ln(f,n);
  178. for(int i=0;i<n;++i) f[i]=MOD(f[i]*k);
  179. p_exp(f,n);
  180. }
  181. // 分治FFT [l,r) F[n] = sum(0<i<=n) F[n-i]G[i]
  182. void DCFFT(ll f[],ll g[],int l,int r) {
  183. static ll A[N],B[N];
  184. if(r-l==1) return ;
  185. int mid=(l+r)>>1,len=mid-l;
  186. DCFFT(f,g,l,mid);
  187. cpy(A,f+l,len); clr(A+len,len); cpy(B,g,len<<1);
  188. p_mul(A,B,len<<1,len<<1,len<<1);
  189. for(int i=mid;i<r;++i) f[i]=MOD(f[i]+A[i-l]);
  190. DCFFT(f,g,mid,r);
  191. }
  192. }
  193. using poly::p_ln;
  194. using poly::p_exp;
  195. using poly::p_inv;
  196. using poly::p_mul;
  197. using poly::NTT;
  198. using poly::ifac;
  199. using poly::fac;
  200. using poly::inv;
  201. using poly::mod;
  202. /*------------------------------- END POLY FAMILY BUCKET ---------------------------------------*/
  203. const int N = (1<<19);
  204. int n,m,nn;
  205. ll a[N],G[N],f[N],h[N];
  206. vector<ll> F[N<<2][2];
  207. #define ls (x<<1)
  208. #define rs (x<<1|1)
  209. void solve(int l=1,int r=n,int x=1) {
  210. if(l==r) {
  211. F[x][0].resize(2,0);
  212. F[x][1].resize(2,0);
  213. F[x][0][0]=1;
  214. F[x][1][0]=1;
  215. F[x][1][1]=mod-a[l];
  216. return ;
  217. }
  218. int mid=(l+r)>>1;
  219. solve(l,mid,ls);solve(mid+1,r,rs);
  220. int n=F[ls][1].size()+F[rs][1].size()-1;
  221. int nn=1<<(int)ceil(log2(n));
  222. F[ls][0].resize(nn,0);F[ls][1].resize(nn,0);
  223. F[rs][0].resize(nn,0);F[rs][1].resize(nn,0);
  224. F[x][0].resize(nn,0);F[x][1].resize(nn,0);
  225. NTT(F[ls][0].begin(),nn,1);
  226. NTT(F[rs][0].begin(),nn,1);
  227. NTT(F[ls][1].begin(),nn,1);
  228. NTT(F[rs][1].begin(),nn,1);
  229. for(int i=0;i<nn;++i)
  230. F[x][1][i]=MOD(F[ls][1][i]*F[rs][1][i]);
  231. for(int i=0;i<nn;++i)
  232. F[x][0][i]=(F[ls][1][i]*F[rs][0][i]+F[ls][0][i]*F[rs][1][i])%mod;
  233. NTT(F[x][0].begin(),nn,-1);
  234. NTT(F[x][1].begin(),nn,-1);
  235. F[x][0].resize(n,0);
  236. F[x][1].resize(n,1);
  237. }
  238. int main() {
  239. red(n);red(m);
  240. nn=1<<(int)ceil(log2(m+1));
  241. poly::Initinv(1<<19);
  242. for(int i=0;i<nn;++i) G[i]=ifac[i+1];
  243. p_ln(G,nn);
  244. for(int i=1;i<=n;++i) {
  245. red(a[i]);a[i]%=mod;
  246. }
  247. solve();
  248. seeln(F[1][0]); seeln(F[1][1]);
  249. for(int i=0;i<nn;++i) {
  250. if(i>=F[1][1].size()) break;
  251. f[i]=F[1][1][i];
  252. }
  253. p_inv(f,nn,h);
  254. clr(f,nn);
  255. for(int i=0;i<nn;++i) {
  256. if(i>=F[1][0].size()) break;
  257. f[i]=F[1][0][i];
  258. }
  259. p_mul(f,h,nn,nn,nn);
  260. outarr(f,nn);
  261. for(int i=0;i<nn;++i) {
  262. G[i]=G[i]*f[i]%mod;
  263. }
  264. p_exp(G,nn);
  265. for(int i=1;i<=m;++i) {
  266. ll ans=fac[i]*G[i]%mod;
  267. printf("%lld ",ans);
  268. }
  269. puts("");
  270. return 0;
  271. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注