/* Author : QedDust413 & Killer_joke need C++20. poly tem IV. */ #include #pragma GCC target("avx2") #include struct auto_timer{ std::chrono::system_clock::time_point lst; auto_timer() : lst(std::chrono::system_clock::now()){ } ~auto_timer(){ std::chrono::duration tott=std::chrono::system_clock::now()-lst; std::clog<inline u32x8 shuffle(u32x8 x){return (u32x8)_mm256_shuffle_epi32((I256)x,typ);} templateinline u32x8 blend(u32x8 x,u32x8 y){return (u32x8)_mm256_blend_epi32((I256)x,(I256)y,typ);} inline u32x8&x8(u32*data){return*((u32x8*)data);} inline const u32x8&x8(const u32*data){return*((const u32x8*)data);} inline u32x8 min_u32(u32x8 x,u32x8 y){return (u32x8)_mm256_min_epu32((I256)x,(I256)y);} constexpr u32x8 padd(u32 x){return (u32x8){x,x,x,x,x,x,x,x};} inline u32x8 loadu_u32x8(const u32*f) {return (u32x8)_mm256_loadu_si256((const __m256i_u*)f);} inline void storeu(void*f,u32x8 x) {_mm256_storeu_si256((__m256i_u*)f,(I256)x);} constexpr u32 get_nr(u32 M){u32 Iv=1;for(int i=0;i<5;++i){Iv*=2-M*Iv;}return Iv;} templateconstexpr u32 sf_md(i64 x){return x%=M,x<0?x+M:x;} constexpr idt bcl(idt x){return ((x<2)?1:idt(2)<>32;} constexpr u32 reduce_s(u64 x){return shrk(reduce(x));} constexpr u32 add(u32 x,u32 y){return shrk2(x+y);} constexpr u32 sub(u32 x,u32 y){return dil2(x-y);} constexpr u32 mul(u32 x,u32 y){return reduce(u64(x)*y);} constexpr u32 mul_s(u32 x,u32 y){return reduce_s(u64(x)*y);} constexpr u32 qpw(u32 a,u32 b,u32 r=R){for(;b;b>>=1,a=mul(a,a)){b&1?r=mul(r,a):r;}return r;} constexpr u32 inv(u32 x){return qpw(x,M-2);} constexpr u32 dvs(u32 x,u32 y){return qpw(y,M-2,x);} constexpr u32 neg(u32 x){return M2-x;} constexpr u32 in(u32 x){return mul(x,R2);} constexpr u32 in_s(u32 x){return mul_s(x,R2);} constexpr u32 out(u32 x){return reduce_s(x);} constexpr bool equals(u32 x,u32 y){return out(x)==out(y);} constexpr void clr(u32&x){x=E;} constexpr u32x8 Rx8=padd(R),Ex8=padd(E),Mx8=padd(M),M2x8=padd(M2),nivx8=padd(niv); inline u32x8 shrk(u32x8 x){return min_u32(x,x-Mx8);} inline u32x8 dil2(u32x8 x){return min_u32(x,x+M2x8);} inline u32x8 shrk2(u32x8 x){return min_u32(x,x-M2x8);} inline u32x8 add(u32x8 x,u32x8 y){return shrk2(x+y);} inline u32x8 sub(u32x8 x,u32x8 y){return dil2(x-y);} inline u32x8 reduce(u64x4 a,u64x4 b){ u64x4 c=fus_mul(u32x8(a),nivx8),d=fus_mul(u32x8(b),nivx8); c=fus_mul(u32x8(c),Mx8),d=fus_mul(u32x8(d),Mx8); return blend<0xaa>(u32x8((a+c)>>32),u32x8(b+d)); } inline u32x8 mul(u32x8 x,u32x8 y){ return reduce(fus_mul(x,y),fus_mul(u32x8(u64x4(x)>>32),u32x8(u64x4(y)>>32))); } inline u32x8 qpw(u32x8 y,u32 b,u32x8 _r=Rx8){u32x8 x=y,r=_r;for(;b;x=mul(x,x),b>>=1){if(b&1){r=mul(r,x);}}return r;} inline u32x8 inv(u32x8 x){return qpw(x,M-2);} inline u32x8 dvs(u32x8 x,u32x8 y){return qpw(y,M-2,x);} inline u32x8 mul_s(u32x8 x,u32x8 y){return shrk(mul(x,y));} inline u32x8 neg(u32x8 x){return M2x8-x;} inline void clr(u32x8&x){x=Ex8;} constexpr u32 _Amul(u32 a,u32 b,u32 c){return mul(a+b,c);} constexpr u32 _Smul(u32 a,u32 b,u32 c){return mul(a-b+M2,c);} inline u32x8 _Amul(u32x8 a,u32x8 b,u32x8 c){return mul(a+b,c);} inline u32x8 _Smul(u32x8 a,u32x8 b,u32x8 c){return mul(a-b+M2x8,c);} templateinline u32x8 Neg(u32x8 x){return blend(x,M2x8-x);} constexpr u32x8 powXx8(u32 X){ u32 X2=mul_s(X,X),X3=mul_s(X2,X),X4=mul_s(X3,X),X5=mul_s(X4,X),X6=mul_s(X5,X),X7=mul_s(X6,X); return (u32x8){R,X,X2,X3,X4,X5,X6,X7}; } constexpr u32 _ADmul(u32 a,u32 b,u32 c,u32 d){return reduce_s(u64(a)*b+u64(c)*d);} inline u32x8 _ADmul(u32x8 a,u32x8 b,u32x8 c,u32x8 d){ return shrk(reduce(fus_mul(a,b)+fus_mul(c,d),fus_mul(u32x8(u64x4(a)>>32),u32x8(u64x4(b)>>32))+fus_mul(u32x8(u64x4(c)>>32),u32x8(u64x4(d)>>32)))); } constexpr u32 sqt(u32 x){ u32 y=R,Im=E; while(shrk(qpw(Im=sub(mul(y,y),x),(M-1)>>1))==R){++y;} u32 a0=y,a1=R,r0=R,r1=E; for(u32 b=(M+1)>>1;b;b>>=1){ if(b&1){std::tie(r0,r1)=std::tuple{_ADmul(r0,a0,mul(r1,a1),Im),_ADmul(r0,a1,r1,a0)};} std::tie(a0,a1)=std::tuple{_ADmul(a0,a0,mul(a1,a1),Im),_ADmul(a0,a1,a1,a0)}; }u32 z=out(r0); return in_s(std::min(z,M-z)); } constexpr u32 pr2_rt(u32 M,u32 _g=2){ for(;equals(qpw(_g,M>>1),R);++_g); return _g; } constexpr u32 Half=shrk(inv(in(2))),nHalf=M-Half; struct vec_v{ u32x8 v; constexpr vec_v(u32 x):v{padd(x)}{} constexpr operator u32()const{return v[0];} constexpr operator u32x8()const{return v;} }; inline void vec_op(auto f,idt n,auto&&op){idt i=0;for(;i+7>lml)); for(int i=lml;i>0;--i){t[i-1]=mul_s(t[i],t[i]);} } constexpr u32 operator[](int i)const{return t[i];} }; struct ntt_info_base4x8{ u32 rt3[lml-2],rt3_I[lml-2]; u32x8 rt4ix8[lml-3],rt4ix8_I[lml-3]; constexpr ntt_info_base4x8(const P_R_Tab&w,const P_R_Tab&wI):rt3{},rt3_I{},rt4ix8{},rt4ix8_I{}{ u32 pr=R,pr_I=R; for(int i=0;iinline void dif_2(u32&x,u32&y){ u32 sum=add(x,y),diff=sub(x,y);x=sum,y=diff; if constexpr(strict){x=shrk(x),y=shrk(y);} } templateinline void dif_4(u32&x,u32&y,u32&z,u32&w){ u32 a=sub(x,z),b=_Smul(y,w,Img); x=add(x,z),y=add(y,w),z=add(a,b),w=sub(a,b),a=add(x,y),b=sub(x,y),x=a,y=b; if constexpr(strict){x=shrk(x),y=shrk(y),z=shrk(z),w=shrk(w);} } templateinline void vec_dif_base4(u32x8*f,idt n){ idt L=n>>1; if(__builtin_ctzll(n)&1){ for(idt j=0;j>=1; }L>>=1; for(idt l=L<<2,k;L;l=L,L>>=2){ u32 r=R,r2=R,r3=nR;k=1; for(auto i=f;i!=(f+n);r=mul_s(r,iab4.rt3[__builtin_ctzll(k++)]),r2=mul_s(r,r),r3=mul_s(r2,neg(r)),i+=l){ auto rx8=padd(r),r2x8=padd(r2),r3x8=padd(r3); for(auto F0=i,F1=F0+L,F2=F1+L,F3=F2+L;F3!=i+l;++F0,++F1,++F2,++F3){ auto f0=shrk2(*F0),f1=mul(*F1,rx8),f2=mul(*F2,r2x8),f3=mul(*F3,r3x8); auto f1f3=_Amul(f1,f3,Imgx8),f02=add(f0,f2),f13=sub(f1,f3),f_02=sub(f0,f2); *F0=f02+f13,*F1=f02-f13+M2x8,*F2=f_02+f1f3,*F3=f_02-f1f3+M2x8; } } } constexpr u32x8 pr2={R,R,R,Img,R,R,R,Img},pr4={R,R,R,R,R,rt1[3],Img,mul_s(Img,rt1[3])}; auto rx8=Rx8; for(idt i=0;i(fi),swaplohi128(fi),pr4); fi=_Amul(Neg<0xcc>(fi),shuffle<0x4e>(fi),pr2); fi=sub(shuffle<0xb1>(fi),Neg<0x55>(fi)); if constexpr(strict){fi=shrk(fi);} } } templateinline void dit_2(u32&x,u32&y){ constexpr u32 iv2=mul_s(inv(in(2)),fx); u32 a=_Amul(x,y,iv2),b=_Smul(x,y,iv2);x=a,y=b; } templateinline void dit_4(u32&x,u32&y,u32&z,u32&w){ constexpr u32 iv4=mul_s(inv(in(4)),fx),Imgi4=mul_s(iv4,Img); u32 a=_Amul(x,y,iv4),b=_Smul(x,y,iv4); x=a,y=b,a=_Amul(z,w,iv4),b=_Smul(w,z,Imgi4),z=sub(x,a),w=sub(y,b),x=add(x,a),y=add(y,b); } templateinline void vec_dit_base4(u32x8*f,idt n){ constexpr u32 nR2=in_s(nR),M8=(M-1)>>3; constexpr u32x8 pr2={nR2,nR2,nR2,in(Img),nR2,nR2,nR2,in(Img)},pr4={fx,fx,fx,fx,fx,mul_s(fx,rt1_I[3]),mul_s(fx,rt1_I[2]),mul_s(fx,mul_s(rt1_I[2],rt1_I[3]))}; auto rx8=padd(M8>>__builtin_ctzll(n)); idt L=1; for(idt i=0;i(fi),shuffle<0xb1>(fi),pr2); fi=_Amul(Neg<0xcc>(fi),shuffle<0x4e>(fi),pr4); fi=_Amul(Neg<0xf0>(fi),swaplohi128(fi),rx8); rx8=mul_s(rx8,iab4.rt4ix8_I[__builtin_ctzll(~i)]); } for(idt l=L<<2,k;L<(n>>1);L=l,l<<=2){ u32 r=R,r2=R,r3=R;k=1; for(auto i=f;i!=(f+n);r=mul_s(r,iab4.rt3_I[__builtin_ctzll(k++)]),r2=mul_s(r,r),r3=mul_s(r2,r),i+=l){ auto rx8=padd(r),r2x8=padd(r2),r3x8=padd(r3); for(auto F0=i,F1=F0+L,F2=F1+L,F3=F2+L;F3!=i+l;++F0,++F1,++F2,++F3){ auto f0=*F0,f1=*F1,f2=neg(*F2),f3=*F3; auto f2f3=_Amul(f3,f2,Imgx8),f01=add(f0,f1),f23=sub(f2,f3),f_01=sub(f0,f1); *F0=sub(f01,f23),*F1=_Amul(f_01,f2f3,rx8),*F2=_Amul(f01,f23,r2x8),*F3=_Smul(f_01,f2f3,r3x8); } } } if(__builtin_ctzll(n)&1){ for(idt j=0;jinline void dif(u32*A,idt lm){ switch(lm){ case 1:if constexpr(strict){A[0]=shrk(A[0]);}break; case 2:dif_2(A[0],A[1]);break; case 4:dif_4(A[0],A[1],A[2],A[3]);break; default:vec_dif_base4((u32x8*)A,lm>>3); } } templateinline void dit(u32*A,idt lm){ switch(lm){ case 1:if constexpr(!equals(fx,R)){A[0]=mul(A[0],fx);}break; case 2:dit_2(A[0],A[1]);break; case 4:dit_4(A[0],A[1],A[2],A[3]);break; default:vec_dit_base4((u32x8*)A,lm>>3); } } }//namespace raw_ntt using raw_ntt::dif; using raw_ntt::dit; //u32* u32 const u32* idt inline u32*alc(idt n){return new(std::align_val_t(32))u32[n];} inline void fre(u32*p){::operator delete[](p,std::align_val_t(32));} templatestruct aligned_alcor{ typedef T value_type; T*allocate(idt n){return new(std::align_val_t(al))T[n];} templatestruct rebind{using other=aligned_alcor;}; void deallocate(T*p,idt){::operator delete[](p,std::align_val_t(al));} }; using vec=std::vector >; templateinline T*cpy(T*f,const T*g,idt n){return (T*)memcpy(f,g,n*sizeof(T));} templateinline T*clr(T*f,idt n){return (T*)memset(f,0,n*sizeof(T));} templateinline T*rcpy(T*f,const T*g,idt n){return std::reverse_copy(g,g+n,f),f;} templateinline void rev(T*f,idt n){std::reverse(f,f+n);} void dot(u32*f,const u32*g,idt n){vec_op(f,g,n,[](auto&fi,auto&gi){fi=mul(fi,gi);});} void dot(u32*f,const u32*g,const u32*h,idt n){vec_op(f,g,h,n,[](auto&fi,auto&gi,auto&hi){return fi=mul(gi,hi);});} void add(u32*f,const u32*g,idt n){vec_op(f,g,n,[](auto&fi,auto&gi){fi=add(fi,gi);});} void add(u32*f,const u32*g,const u32*h,idt n){vec_op(f,g,h,n,[](auto&fi,auto&gi,auto&hi){return fi=add(gi,hi);});} void sub(u32*f,const u32*g,idt n){vec_op(f,g,n,[](auto&fi,auto&gi){fi=sub(fi,gi);});} void sub(u32*f,const u32*g,const u32*h,idt n){vec_op(f,g,h,n,[](auto&fi,auto&gi,auto&hi){return fi=sub(gi,hi);});} void adddot(u32*a,const u32*b,const u32*c,const u32*d,idt n){vec_op(a,b,c,d,n,[](auto&A,auto&B,auto&C,auto&D){A=_ADmul(A,B,C,D);});} void vec_multi_iv(u32x8*f,const u32x8*g,idt n){ if(n==0){return;} f[0]=g[0];for(idt i=1;i>3); for(idt i=(n>>3)<<3;iinline void conv(u32*f,u32*g,idt lm){dif(f,lm),dif(g,lm),dot(f,g,lm),dit(f,lm);} templatestruct sim_inf_seq{ using T=typename V::value_type; std::function f; mutable V v; sim_inf_seq(auto&&F):f{F}{} const T*rsv(idt l)const{ idt ol=v.size(); if(l>ol)[[unlikely]]{l=std::max((l+alz-1)&-alz,ol<<1),v.resize(l),f(v.data(),ol,l);} return v.data(); } const T&operator[](idt pos)const{return rsv(pos+1)[pos];} }; sim_inf_seq Id=[](u32*f,idt l,idt r){ for(;l<8;++l){f[l]=in(l);} constexpr auto va8=padd(in(8)); for(auto i=l;i>3); }, Fac=[](u32*f,idt l,idt r){ auto id=Id.rsv(r); if(l==0){f[0]=R,l=1;} for(auto i=l;i16){ for(;i<8;++i){f[i-1]=mul(g[i],id[i]);} for(;i+716){ for(;(i&7)!=7;--i){f[i]=mul(g[i-1],iv[i]);} for(;i>7;i-=8){x8(f+i-7)=mul(loadu_u32x8(g+i-8),x8(iv+i-7));}; } for(;i>0;--i){f[i]=mul(g[i-1],iv[i]);}f[0]=C; } void scanp(u32*f,idt n=1){ for(idt i=0;i>f[i],f[i]=in(f[i]); } } void printp(const u32*f,idt n=1){ for(idt i=0;i(o,t),cpy(f+m,o+m,xl-m); }fre(o); } void quo(u32*f,const u32*g,const u32*h,idt n){ if(n<=64){ idt lm=bcl(n<<1);auto o=alc(lm*2),s=o+lm; inv(o,h,n),clr(o+n,lm-n),cpy(s,g,n),clr(s+n,lm-n),conv(o,s,lm),cpy(f,o,n),fre(o); return; } idt bn=bcl(n)>>4,bt=(n+bn-1)/bn,bn2=bn<<1; auto o=alc(bn2),A=alc(bn2); inv(o,h,bn),clr(o+bn,bn),clr(cpy(A,g,bn)+bn,bn),conv(A,o,bn2); auto Nh=alc(bn2*bt),nh=Nh,Nf=alc(bn2*(bt-1)),nf=Nf; cpy(f,A,bn),clr(cpy(nh,h,bn)+bn,bn),dif(nh,bn2); for(idt ds=bn,xl;ds(nf,bn2),clr(A,bn2),nf+=bn2;auto nH=nh,nF=Nf,nH1=nH-bn2; for(idt dj=0;djvoid __expi(u32*f,u32*h,const u32*g,idt n){ f[0]=h[0]=R;if(n==1){return;} auto lm=bcl(n); auto id=Id.rsv(lm),iv=Iv.rsv(lm); auto o=alc(lm*3),A=o+lm,B=A+lm; clr(A,lm),A[0]=A[1]=R; for(idt t=2,m=1,xl;t<=lm;m=t,t<<=1){ xl=std::min(n,t),dot(o,id,g,m),dif(o,m),dot(o,A,m),dit(o,m);dot(o+m,f,id,m); vec_op(o+m,o,m,[](auto&fi,auto&gi){fi=sub(fi,gi),clr(gi);}),dif(o,t); clr(cpy(B,h,m)+m,m),dif(B,t),dot(o,B,t),dit(o,t),dot(clr(o,m)+m,iv+m,m); sub(o+m,g+m,xl-m),dif(o,t),dot(A,o,t),dit(A,t),cpy(f+m,A+m,xl-m); if(c_inv||(t!=lm)){ cpy(A,f,m),dif(A,std::min(t<<1,lm)),dot(o,A,B,t),dit(o,t),clr(o,m); dif(o,t),dot(o,B,t),dit(o,t),cpy(h+m,o+m,xl-m); } }fre(o); } void exp(u32*f,const u32*g,idt n){ if(n<=64){ u32*p=alc(n); return __expi(f,p,g,n),fre(p); } idt bn=bcl(n)>>4,bt=(n+bn-1)/bn,bn2=bn<<1; auto o=alc(bn2),h=alc(bn2); auto id=Id.rsv(n),iv=Iv.rsv(n); __expi(f,h,g,bn),clr(h+bn,bn),dif(h,bn2); auto Ng=alc(bn2*bt),ng=Ng,Nf=alc(bn2*(bt-1)),nf=Nf; dot(ng,g,id,bn),clr(ng+bn,bn),dif(ng,bn2); for(idt ds=bn,xl;ds(nf,bn2),clr(o,bn2),nf+=bn2; auto nG=ng,nF=Nf,nG1=nG-bn2; for(idt dj=0;dj(o,bn2); dot(o,iv+ds,xl),clr(o+xl,bn2-xl),dif(o,bn2),dot(o,Nf,bn2),dit(o,bn2),cpy(f+ds,o,xl); }fre(o),fre(h),fre(Ng),fre(Nf); } void sqrtinv(u32*f,const u32*g,idt n){ auto lm=bcl(n); auto o=alc(lm*4),h=o+lm*2; f[0]=inv(sqt(g[0])); for(idt r=4,t=2,m=1,xl;t<=lm;m=t,t=r,r<<=1){ xl=std::min(n,t),clr(cpy(o,f,m)+m,r-m),clr(cpy(h,g,xl)+xl,r-xl),dif(o,r),dif(h,r); vec_op(h,o,r,[](auto&fi,auto&gi){fi=mul(mul(fi,gi),mul(gi,gi));}),dit(h,r),cpy(f+m,h+m,xl-m); }fre(o); } templatevoid __sqrti(u32*f,u32*h,const u32*g,idt n){ auto lm=bcl(n); f[0]=sqt(g[0]),h[0]=inv(f[0]); auto o=alc(lm*3),H=o+lm,F=H+lm; F[0]=f[0]; for(idt t=2,m=1,xl;t<=lm;m=t,t<<=1){ xl=std::min(t,n),dot(F,F,m),dit(F,m); vec_op(F,F+m,g,g+m,m,[](auto&a0,auto&a1,auto&b0,auto&b1){a1=sub(sub(a0,b0),b1),clr(a0);}); clr(cpy(H,h,m)+m,m),conv(F,H,t),cpy(f+m,F+m,xl-m); if(c_inv||(t!=lm)){ dif(cpy(o,f,t),t),cpy(F,o,t),dot(o,H,t),dit(o,t),dif(clr(o,m),t),dot(o,H,t),dit(o,t),cpy(h+m,o+m,xl-m); } }fre(o); } void sqrt(u32*f,const u32*g,idt n){ if(n<=64){u32*p=alc(n);return __sqrti(f,p,g,n),fre(p);} idt bn=bcl(n)>>4,bt=(n+bn-1)/bn,bn2=bn<<1; auto o=alc(bn2),jok=alc(bn2); __sqrti(f,o,g,bn),clr(o+bn,bn),dif(o,bn2); auto Nf=alc(bn2*(bt-1)),nf=Nf; for(idt ds=bn,xl;ds(nf,bn2),nf+=bn2; auto nF=nf,nF1=nf-bn2,NF=Nf; for(idt i=0;i(jok,bn2),clr(jok+bn,bn),sub(jok,g+ds,xl),dif(jok,bn2),dot(jok,o,bn2),dit(jok,bn2),cpy(f+ds,jok,xl); }fre(o),fre(jok),fre(Nf); } void Ci(u32*f,u32 z,idt n){ u32 x=R;idt i=0; for(;i(n,8);++i,x=mul(x,z)){f[i]=x;} if(n>16){ u32x8 xx8=padd(x); for(;i+7(k)),f,n),exp(f,h,n),fre(h); } namespace ntt_op{ using namespace raw_ntt; sim_inf_seq sim_wn=[](u32*f,idt l,idt r){ for(idt i=std::max(1,l);iinline void dif2(u32*f,idt l){ cpy(f+l,f,l),dit(f+l,l),dot(f+l,sim_wn.v.data()+l,l),dif(f+l,l); } constexpr u32 Two=in(2); templateinline void dif2_c1(u32*f,idt l){ cpy(f+l,f,l),dit(f+l,l),dot(f+l,sim_wn.v.data()+l,l),f[l]=sub(Two,f[l]),dif(f+l,l); } templateinline void dif2_xn(u32*f,idt l){ cpy(f+l,f,l),dit(f+l,l),dot(f+l,sim_wn.v.data()+l,l),f[l]=sub(f[l],Two),dif(f+l,l); } inline void rev_dif(u32*f,const u32*g,idt l){ dot(f,bv_wn.v.data(),g,l); for(idt i=2;i(x8(g+i)));} for(u32 x,y;i+132){ rev_dif(buf+lm,buf,lm),sim_wn.rsv(lm); for(int dep=1;dep0;--dep){ idt t=idt(1)<>1; for(;rt)?dot(nw+i,lt+i,lt+i+t,t):((void)cpy(nw+i,lt+i,t));dif2(nw+i,t);} } dot(buf,lt,lt+lm,lm),dit(buf,lm); if(n==lm){buf[lm]=R,buf[0]=sub(buf[0],R);} deriv(buf+lm2,buf,n+1),rev(buf,n+1),rev(buf+lm2,n); quo(buf+lm2,buf+lm2,buf,n),clr(buf+lm,lm-n),rcpy(buf+lm2-n,buf+lm2,n); for(int dep=lgn;dep>0;--dep){ lt=GG[dep-1]; idt t=idt(1)<>1; for(;r(buf+l,t);} if(l(buf+l,t);} } adddot(buf,lt+lm,buf+lm,lt,lm),dit(buf,lm),cpy(f,buf,n),fre(buf); for(int dep=0;dep>1; auto wi=bv_wi2.rsv(hm); sim_wn.rsv(lm); for(;k;k>>=1,iv=mul(iv,Half)){ dot_neg(p,q,lm),dot_neg(q,q,lm); if(k&1){for(idt i=0;i>=1,dit(p,lm),dit(q,lm),clr(p+hm,hm),clr(q+hm,hm),dif(p,lm),dif(q,lm);} else{dif2(p,hm),dif2(q,hm);} } return mul(dvs(p[0],q[0]),iv); } // p / q (deg(p) < deg(q))[k] u32 quo_at(const u32*f,const u32*g,idt n,idt m,idt k){ idt lm=bcl(m),lm2=lm*2; auto df=alc(lm2),dg=alc(lm2); cpy(df,f,n),clr(df+n,lm2-n),cpy(dg,g,m),clr(dg+m,lm2-m); u32 res={}; if(k>1,rr=(r+1)>>1,nn=rr-ll; auto res=alc(nn); __test_inv_range(res,p,n,ll,rr); //printp(res,10); idt llm=bcl(r-l+n-1); auto pp=alc(llm),qq=alc(llm); clr(pp,llm),clr(qq,llm); for(idt i=0;i struct matrix{ int H,W; vector> table; matrix(int h,int w) : H(h),W(w){ table.resize(h,vector(w)); } int size(){ return H; } matrix pow(long long N){ assert(H==W); assert(0<=N); matrix x=*this; matrix r(H,H); for(int i=0;i>=1; } return r; } vector& operator[](int index){ assert(index using namespace atcoder; using mint=modint998244353; int main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int N,k; long long M; scanf("%d%lld%d",&N,&M,&k); for(;k--;){ int C; scanf("%d",&C); vector> P(6,vector(6)); //P[i][j]:X=iからスタートして,X=N+j(ピッタリ)で終わるサイコロの振り方であって,常にX \not \equiv C (mod N)である場合 for(int i=0;i<6;i++){ for(int j=0;j<6;j++){ if(i==C){ P[i][j]=0; continue; } if(j==C){ P[i][j]=0; continue; } if(i Q(6,6); for(int i=0;i<6;i++){ for(int j=0;j<6;j++){ Q[i][j]=P[j][i]; } } Q=Q.pow(M-2);//to do:M=1の場合に場合分けして書く matrix R(6,1); for(int i=0;i<6;i++){ R[i][0]=P[0][i]; } Q*=R; vector S(6); for(int i=0;i<6;i++){ if(Q[i][0]==0){ continue; } for(int j=0;j<6;j++){ //iからN+jに動く //N~N+jの間のCについては無視 if(i=0;i--){ for(int j=i-1;j>=0;j--){ S[i]-=S[j]; } ans+=S[i]; } printf("%d\n",ans.val()); } }