QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#305300#8010. Hierarchies of Judgeshos_lyricAC ✓1649ms209196kbC++1438.9kb2024-01-15 03:40:172024-01-15 03:40:18

Judging History

你现在查看的是最新测评结果

  • [2024-01-15 03:40:18]
  • 评测
  • 测评结果:AC
  • 用时:1649ms
  • 内存:209196kb
  • [2024-01-15 03:40:17]
  • 提交

answer

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

using Int = long long;

template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")


// https://fjzzq2002.blog.uoj.ac/blog/7281
/*
 A Better Polynomial Template
	by zzq
*/
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
typedef long long ll;
#define fi first
#define se second
#define SS 524288 //max length of DFT
#define PS (SS*20+1000) //pool for temp arrays
#define PS2 (SS*20+1000) //another pool, see ocmul
#define FS 666666 //length of fac, rfac
const int MOD=998244353;
ll qp(ll a,ll b) {
	ll ans=1; a%=MOD;
	while(b) {
		if(b&1) ans=ans*a%MOD;
		a=a*a%MOD; b>>=1;
	}
	return ans;
}
int getK(int n) {int s=1; while(s<n) s<<=1; return s;}
typedef unsigned us;
typedef unsigned long long ull;
namespace RawNTT {
us pool[SS*8+10000],*ptr=pool;
us *p0[SS],*p1[SS],*q0[SS],*q1[SS];
template<class T>
void bit_flip(T*p,int t) {
	for(int i=0,j=0;i<t;++i)
	{
		if(i>j) swap(p[i],p[j]);
		for(int l=t>>1;(j^=l)<l;l>>=1);
	}
}
void prep(int n) {
	static int t=1;
	for(;t<n;t<<=1) {
		int g=qp(3,(MOD-1)/(t*2));
		us*p,*q;
		p=p0[t]=ptr; ptr+=max(t,16); p[0]=1;
		for(int m=1;m<t;++m)
			p[m]=p[m-1]*(ull)g%us(MOD);
		bit_flip(p,t);
		q=q0[t]=ptr; ptr+=max(t,16);
		for(int i=0;i<t;++i)
			q[i]=(ull(p[i])<<32)/MOD;
		g=qp(g,MOD-2);
		p=p1[t]=ptr; ptr+=max(t,16); p[0]=1;
		for(int m=1;m<t;++m)
			p[m]=p[m-1]*(ull)g%us(MOD);
		bit_flip(p,t);
		q=q1[t]=ptr; ptr+=max(t,16);
		for(int i=0;i<t;++i)
			q[i]=(ull(p[i])<<32)/MOD;
	}
}
typedef unsigned long long ull;
us my_mul(us a,us b,us c) {
	return b*(ull)a-((ull(a)*c)>>32)*ull(998244353);
}
void ntt(us* x,int n,bool f=true) {
	prep(n); int t=n>>1;
	for(int m=1;m<n;m<<=1,t>>=1)
	{
		us *p=p0[m],*q=q0[m],*xa=x,*xb=x+t;
		for(int i=0;i<m;++i,xa+=t+t,xb+=t+t)
			for(int j=0;j<t;++j)
			{
				us u=xa[j]-(xa[j]>=us(MOD+MOD))*us(MOD+MOD);
				us v=my_mul(xb[j],p[i],q[i]);
				xa[j]=u+v; xb[j]=u-v+us(MOD+MOD);
			}
	}
	for(int i=0;i<n;++i)
		x[i]-=(x[i]>=us(MOD+MOD))*us(MOD+MOD),
		x[i]-=(x[i]>=us(MOD))*us(MOD);
	if(f) bit_flip(x,n);
}
void intt(us* x,int n,bool f=true) {
	prep(n); int t=1;
	if(f) bit_flip(x,n);
	for(int m=(n>>1);m;m>>=1,t<<=1)
	{
		us *p=p1[m],*q=q1[m],*xa=x,*xb=x+t;
		for(int i=0;i<m;++i,xa+=t+t,xb+=t+t)
			for(int j=0;j<t;++j)
			{
				us u=xa[j],v=xb[j];
				xa[j]=u+v-(u+v>=us(MOD+MOD))*us(MOD+MOD);
				xb[j]=my_mul(u-v+us(MOD+MOD),p[i],q[i]);
			}
	}
	us rn=qp(n,MOD-2);
	for(int i=0;i<n;++i)
		x[i]=x[i]*(ull)rn%MOD;
}
}


union mi //modint, treat as POD
{
	us w;
	mi() {w=0;}
	mi(us u) {w=u;}
	mi(int u) {u%=MOD; w=u+((u<0)?MOD:0);}
	explicit operator us() const {return w;}
	explicit operator int() const {return w;}
};
mi operator + (const mi& a,const mi& b)
{return mi{a.w+b.w-((a.w+b.w>=MOD)?(MOD):0)};}
mi operator - (const mi& a,const mi& b)
{return mi{a.w-b.w+((a.w<b.w)?(MOD):0)};}
mi operator * (const mi& a,const mi& b)
{return mi{us((ull)a.w*b.w%MOD)};}
mi operator / (const mi& a,const mi& b)
{return mi{us((ull)a.w*qp(b.w,MOD-2)%MOD)};}
mi inv(const mi& a)
{return mi{us(qp(a.w,MOD-2))};}
bool operator == (const mi& a,const mi& b) {return a.w==b.w;}
bool operator != (const mi& a,const mi& b) {return a.w!=b.w;}
mi& operator += (mi& a,const mi& b)
{a.w=a.w+b.w-((a.w+b.w>=MOD)?MOD:0); return a;}
mi& operator -= (mi& a,const mi& b)
{a.w=a.w-b.w+((a.w<b.w)?MOD:0); return a;}
mi operator - (const mi& a) {return mi{a.w?(MOD-a.w):0};}
mi& operator ++ (mi& a) {a.w=a.w+1-((a.w+1>=MOD)?MOD:0); return a;}
mi& operator -- (mi& a) {a.w=a.w-1+(a.w?0:MOD); return a;}
//what could possibly go wrong?
void ntt(mi* x,int n,bool f=true) {RawNTT::ntt((us*)x,n,f);}
void intt(mi* x,int n,bool f=true) {RawNTT::intt((us*)x,n,f);}
void fft(mi* x,int n,bool r,bool f=true) {
	if(r) intt(x,n,f); else ntt(x,n,f);
}
void cp(mi*t,mi*s,int K) {
	if(s) memcpy(t,s,sizeof(mi)*K);
	else memset(t,0,sizeof(mi)*K);
}
void cp(mi*t,mi s,int K) {
	if(s.w==0) memset(t,0,sizeof(mi)*K);
	else for(int i=0;i<K;++i) t[i]=s;
}
mi qp(mi a,ll b) {
	mi x=1;
	while(b) {
		if(b&1) x=x*a;
		a=a*a; b>>=1;
	}
	return x;
}
mi fac[FS],rfac[FS];
struct Fac_Initer {
Fac_Initer() {
	fac[0]=1;
	for(int i=1;i<FS;++i) fac[i]=fac[i-1]*i;
	rfac[FS-1]=inv(fac[FS-1]);
	for(int i=FS-1;i;--i) rfac[i-1]=rfac[i]*i;
}
}fac__initer__;
mi mempool[PS],*pt=mempool;
mi*alc(int t,bool c=0) {
	if(c) cp(pt,0,t);
	pt+=t;
	assert(pt<mempool+PS);
	return pt-t;
}
void ginv_K(mi*x,mi*o,int K) {
	if(K==1) {
		o[0]=inv(x[0]);
		return;
	}
	ginv_K(x,o,K>>1);
	mi*fo=alc(K,1),*fx=alc(K),*fw=alc(K);
	cp(fo,o,(K>>1)); fft(fo,K,0); cp(fx,x,K); fft(fx,K,0);
	for(int i=0;i<K;++i) fw[i]=fx[i]*fo[i];
	fft(fw,K,1); cp(fw,fw+(K>>1),K>>1);
	cp(fw+(K>>1),0,K>>1); ntt(fw,K);
	for(int i=0;i<K;++i) fw[i]=fw[i]*fo[i];
	fft(fw,K,1);
	for(int i=0;i<(K>>1);++i) o[i+(K>>1)]=-fw[i];
	pt-=K+K+K;
}
void ginv(mi*x,mi*o,int n) {
	int K=getK(n);
	mi *fx=alc(K,1),*fo=alc(K);
	cp(fx,x,n); ginv_K(fx,fo,K);
	cp(o,fo,n); pt-=K+K;
}
void gdiv(mi*a,mi*b,mi*d,int n,int m) {
	int s=getK(max(n,m));
	mi *ra=alc(s+s,1),*rb=alc(s+s,1);
	for(int i=0;i<n;++i) ra[i]=a[n-1-i];
	for(int i=0;i<m;++i) rb[i]=b[m-1-i];
	ginv(rb,rb,s); fft(ra,s+s,0); fft(rb,s+s,0);
	for(int i=0;i<s+s;++i) rb[i]=ra[i]*rb[i];
	fft(rb,s+s,1); for(int i=0;i<=n-m;++i) d[i]=rb[n-m-i];
	pt-=s*4;
}
void gdiv(mi*a,mi*b,mi*d,mi*r,int n,int m) {
	gdiv(a,b,d,n,m);
	int s=getK(n+1);
	mi *bb=alc(s,1),*dd=alc(s,1);
	cp(bb,b,m); cp(dd,d,n-m+1);
	fft(bb,s,0); fft(dd,s,0);
	for(int i=0;i<s;++i)
		bb[i]=-bb[i]*dd[i];
	fft(bb,s,1);
	for(int i=0;i<m-1;++i)
		r[i]=a[i]+bb[i];
	pt-=s*2;
}
void gln(mi*a,mi*b,int n) {
	int s=getK(n+n);
	mi *ra=alc(s,1);
	ginv(a,ra,n);
	mi *rb=alc(s,1);
	for(int i=0;i+1<n;++i)
		rb[i]=a[i+1]*(i+1);
	fft(ra,s,0); fft(rb,s,0);
	for(int i=0;i<s;++i)
		ra[i]=ra[i]*rb[i];
	fft(ra,s,1); b[0]=0;
	for(int i=1;i<n;++i)
		b[i]=ra[i-1]*rfac[i]*fac[i-1];
	pt-=s*2;
}
mi sqrt_f0; 
void gsqrt_K(mi*f,mi*g,mi*h,int K,bool ch=1) {
	static mi gh[SS];
	if(K==1) {
		assert(sqrt_f0*sqrt_f0-f[0]==0);
		g[0]=sqrt_f0;
		h[0]=inv(sqrt_f0);
		gh[0]=sqrt_f0;
		return;
	}
	gsqrt_K(f,g,h,K>>1);
	mi*fh=alc(K,1),*gg=alc(K>>1),*rr=alc(K,1);
	cp(fh,h,(K>>1)); fft(fh,K,0); cp(gg,gh,K>>1);
	for(int i=0;i<(K>>1);++i)
		gg[i]=gg[i]*gg[i];
	fft(gg,K>>1,1);
	for(int i=0;i<(K>>1);++i)
		rr[i+(K>>1)]=gg[i]-f[i]-f[i+(K>>1)];
	fft(rr,K,0);
	for(int i=0;i<K;++i)
		rr[i]=rr[i]*fh[i]*((MOD+1)/2);
	fft(rr,K,1);
	for(int i=(K>>1);i<K;++i)
		g[i]=-rr[i];
	if(ch) {
		mi *fg=alc(K),*fw=alc(K);
		cp(fg,g,K); fft(fg,K,0);
		for(int i=0;i<K;++i) fw[i]=fg[i]*fh[i];
		fft(fw,K,1);
		for(int i=0;i<(K>>1);++i) fw[i]=fw[i+(K>>1)];
		cp(fw+(K>>1),0,K>>1); fft(fw,K,0);
		for(int i=0;i<K;++i) fw[i]=fw[i]*fh[i];
		fft(fw,K,1);
		for(int i=0;i<(K>>1);++i) h[i+(K>>1)]=-fw[i];
		cp(gh,fg,K); pt-=K+K;
	}
	pt-=K+K+(K>>1);
}
void gsqrt(mi*f,mi*g,int n) {
	int s=getK(n);
	mi *mf=alc(s,1),
	*mg=alc(s),*mh=alc(s);
	cp(mf,f,n); gsqrt_K(mf,mg,mh,s,0);
	cp(g,mg,n); pt-=s+s+s;
}
void gexp_K(mi*f,mi*g,mi*h,int K,bool ch=1) {
	if(K==1) {
		g[0]=h[0]=1;
		return;
	}
	gexp_K(f,g,h,K>>1);
	mi*gg=alc(K>>1),*hh=alc(K>>1),*fh=0,
	*dg=alc(K>>1),*t1=alc(K,1),*t2=alc(K,1);
	dg[(K>>1)-1]=0;
	for(int i=0;i+1<(K>>1);++i)
		dg[i]=g[i+1]*(i+1);
	cp(gg,g,K>>1); mi c=0;
	for(int i=0;i<(K>>1);++i)
		c=c+dg[i]*h[((K>>1)-1)-i];
	if(!ch)
		cp(hh,h,K>>1), fft(hh,K>>1,0);
	else {
		fh=alc(K,1); cp(fh,h,(K>>1)); fft(fh,K,0);
		for(int i=0;i<K;i+=2) hh[i>>1]=fh[i];
	}
	fft(gg,K>>1,0); fft(dg,K>>1,0);
	for(int i=0;i<(K>>1);++i) gg[i]=gg[i]*hh[i];
	fft(gg,K>>1,1);
	for(int i=0;i<(K>>1);++i)
		t1[i+(K>>1)]=(i==0)-gg[i];
	for(int i=0;i+1<(K>>1);++i)
		t2[i]=f[i+1]*(i+1);
	fft(t1,K,0); fft(t2,K,0);
	for(int i=0;i<K;++i) t1[i]=t1[i]*t2[i];
	fft(t1,K,1);
	for(int i=0;i<(K>>1);++i) t1[i]=0;
	for(int i=0;i+1<K;++i)
		t1[i]=t1[i]-f[i+1]*(i+1);
	for(int i=0;i<(K>>1);++i) dg[i]=dg[i]*hh[i];
	fft(dg,K>>1,1); mi r;
	for(int i=0;i<(K>>1);++i)
		r=(i+1==(K>>1))?c:(f[i+1]*(i+1)),
		t1[i]=t1[i]+r,t1[i+(K>>1)]=t1[i+(K>>1)]+dg[i]-r;
	t2[0]=0;
	for(int i=0;i+1<K;++i)
		t2[i+1]=t1[i]*rfac[i+1]*fac[i];
	cp(t1,g,K>>1); cp(t1+(K>>1),0,K>>1);
	fft(t1,K,0); fft(t2,K,0);
	for(int i=0;i<K;++i) t1[i]=t1[i]*t2[i];
	fft(t1,K,1);
	for(int i=(K>>1);i<K;++i)
		g[i]=-t1[i];
	pt-=K*2+(K>>1)*3;
	if(ch) {
		mi *fg=alc(K),*fw=alc(K);
		cp(fg,g,K); fft(fg,K,0);
		for(int i=0;i<K;++i) fw[i]=fg[i]*fh[i];
		fft(fw,K,1);
		for(int i=0;i<(K>>1);++i) fw[i]=fw[i+(K>>1)];
		cp(fw+(K>>1),0,K>>1); fft(fw,K,0);
		for(int i=0;i<K;++i) fw[i]=fw[i]*fh[i];
		fft(fw,K,1);
		for(int i=0;i<(K>>1);++i) h[i+(K>>1)]=-fw[i];
		pt-=K+K+K;
	}
}
void gexp(mi*f,mi*g,int n) {
	int s=getK(n);
	mi *mf=alc(s,1),
	*mg=alc(s),*mh=alc(s);
	cp(mf,f,n); gexp_K(mf,mg,mh,s,0);
	cp(g,mg,n); pt-=s+s+s;
}
string to_string(mi f) {
	return to_string((int)f);
}
string pretty_guess(mi x,int max_dem=1000) {
	string s=to_string((int)x);
	auto upd=[&](string v) {
		if(v.size()<s.size()) s=v;
	};
	upd("-"+to_string((int)(-x)));
	for(int i=1;i<=max_dem;++i) {
		mi w=x*i;
		upd(to_string((int)w)+"/"+to_string(i));
		upd("-"+to_string((int)(-w))+"/"+to_string(i));
	}
	return s;
}
ostream& operator << (ostream& os,const mi& m) {
	os<<m.w; return os;
}
istream& operator >> (istream& is,mi& m) {
	int x; is>>x; m=x; return is;
}
namespace QR{
typedef pair<ll,ll> pll; ll pll_s;
inline pll mul(pll a,pll b,ll p) {
	pll ans;
	ans.fi=a.fi*b.fi%p+a.se*b.se%p*pll_s%p;
	ans.se=a.fi*b.se%p+a.se*b.fi%p;
	ans.fi%=p; ans.se%=p; return ans;
}
pll qp(pll a,ll b,ll c) {
	pll ans(1,0);
	while(b) {
		if(b&1) ans=mul(ans,a,c);
		a=mul(a,a,c); b>>=1;
	}
	return ans;
}
ll qp(ll a,ll b,ll c) {
	ll ans=1;
	while(b) {
		if(b&1) ans=ans*a%c;
		a=a*a%c; b>>=1;
	}
	return ans;
}
int mod_sqrt(ll a,ll p=MOD) {
	if(!a) return 0;
	if(p==2) return 1;
	ll w,q;
	while(1) {
		w=rand()%p; q=w*w-a;
		q=(q%p+p)%p;
		if(qp(q,(p-1)/2,p)!=1)
			break;
	}
	pll_s=q;
	pll rst=qp(pll(w,1),(p+1)/2,p);
	ll ans=rst.fi; ans=(ans%p+p)%p;
	return min(ans,p-ans);
}
}
using QR::mod_sqrt;


#include <functional>
int default_shrink=-1; //mod x^n
struct poly {
vector<mi> coeff;
int shrink_len;
void rev() {
	fit_shrink();
	reverse(coeff.begin(),coeff.end());
}
void insert(mi x) {
	coeff.insert(coeff.begin(),x); shrink();
}
mi& operator [] (int x) {
	if((x<0)||(shrink_len!=-1&&x>=shrink_len))
		throw out_of_range("invalid offset");
	if((int)coeff.size()<x+1) coeff.resize(x+1);
	return coeff[x];
}
mi operator [] (int x) const {
	if((x<0)||(shrink_len!=-1&&x>=shrink_len))
		throw out_of_range("invalid offset");
	if((int)coeff.size()<x+1) return mi(0);
	return coeff[x];
}
mi get(int x) const {
	if((x<0)||(shrink_len!=-1&&x>=shrink_len))
		return 0;
	if((int)coeff.size()<x+1) return mi(0);
	return coeff[x];
}
explicit poly(int shrink_len_=default_shrink):
	shrink_len(shrink_len_){
}
poly(vector<mi> coeff_,int shrink_len_=default_shrink):
	coeff(coeff_),shrink_len(shrink_len_){
	this->shrink();
}
poly(vector<int> coeff_,int shrink_len_=default_shrink):
	shrink_len(shrink_len_){
	this->coeff.resize(coeff_.size());
	for(int i=0;i<(int)coeff.size();++i) this->coeff[i]=coeff_[i];
	this->shrink();
}
void clean_maybe() {
	if(is_poly())
		while(coeff.size()&&coeff.back()==0)
			coeff.pop_back();
}
void clean() {
	assert(is_poly());
	clean_maybe();
}
void fit_shrink() {
	assert(is_series());
	coeff.resize(shrink_len);
}
void set_shrink(int shrink_len_=default_shrink) {
	this->shrink_len=shrink_len_; this->shrink();
}
void dump(char e=0,bool g=1,int l=9) const {
	auto format=[&](mi num) {
		return g?pretty_guess(num):to_string(num);
	};
	int u=(int)coeff.size()-1;
	while(u>=0&&coeff[u]==0) --u;
	if(u<0) {
		printf("{}");
	}
	else {
		for(int j=0;j<=u&&j<=l;++j)
			printf("%c%s","{,"[j!=0],format(coeff[j]).c_str());
		if(u>l)
			printf("...%s(x^%d)",format(coeff[u]).c_str(),u);
		printf("}");
	}
	if(shrink_len==-1)
		printf(" (poly)");
	else printf(" (mod x^%d)",shrink_len);
	if(e) putchar(e);
}
mi* coeff_ptr() {
	if(!coeff.size()) return 0;
	return coeff.data();
}
int size() const {
	return coeff.size();
}
void reserve(int l) {
	if(shrink_len!=-1)
		l=min(l,shrink_len);
	if(l>(int)coeff.size())
		coeff.resize(l);
}
void print_shrink(char e) {
	fit_shrink();
	for(int i=0;i<shrink_len;++i) {
		if(i) printf(" ");
		printf("%d",(int)coeff[i]);
	}
	if(e) printf("%c",e);
}
void print_len(int s,char e) {
	for(int i=0;i<s;++i) {
		if(i) printf(" ");
		printf("%d",(int)get(i));
	}
	if(e) printf("%c",e);
}
void shrink() {
	if(shrink_len!=-1&&(int)coeff.size()>shrink_len)
		coeff.resize(shrink_len);
}
bool is_poly() const {
	return shrink_len==-1;
}
bool is_series() const {
	return shrink_len!=-1;
}
mi eval(mi x) {
	assert(is_poly());
	mi w=0;
	for(int i=size()-1;i>=0;--i)
		w=w*x+coeff[i];
	return w;
}
};
void share_shrink(poly&a,poly&b) {
	int l=max(a.shrink_len,b.shrink_len);
	a.set_shrink(l);b.set_shrink(l);
}
poly ginv(poly p) {
	p.fit_shrink();
	ginv(p.coeff_ptr(),p.coeff_ptr(),p.shrink_len);
	return p;
}
poly gln(poly p) {
	p.fit_shrink();
	gln(p.coeff_ptr(),p.coeff_ptr(),p.shrink_len);
	return p;
}
poly gsqrt(poly p,mi f0=mi(1)) {
	p.fit_shrink(); sqrt_f0=f0;
	gsqrt(p.coeff_ptr(),p.coeff_ptr(),p.shrink_len);
	return p;
}
poly gexp(poly p) {
	p.fit_shrink();
	gexp(p.coeff_ptr(),p.coeff_ptr(),p.shrink_len);
	return p;
}
int merge_shrink(int s1,int s2) {
	if(s1==-1) return s2;
	if(s2==-1) return s1;
	assert(s1==s2); //usually s1=s2
	return min(s1,s2);
}
//guess this is pretty clean
poly operator + (const poly& a,const poly& b) {
	poly c(merge_shrink(a.shrink_len,b.shrink_len));
	c.reserve(max(a.size(),b.size()));
	for(int i=0;i<c.size();++i) c[i]=a[i]+b[i];
	return c;
}
poly operator - (const poly& a,const poly& b) {
	poly c(merge_shrink(a.shrink_len,b.shrink_len));
	c.reserve(max(a.size(),b.size()));
	for(int i=0;i<c.size();++i) c[i]=a[i]-b[i];
	return c;
}
poly operator * (mi v,poly a) {
	for(auto&t:a.coeff) t=t*v;
	return a;
}
poly operator * (poly a,mi v) {
	for(auto&t:a.coeff) t=t*v;
	return a;
}
poly operator + (poly a,mi b) {
	a.reserve(1);
	if(a.size()) a[0]+=b;
	return a;
}
poly operator - (poly a,mi b) {
	a.reserve(1);
	if(a.size()) a[0]-=b;
	return a;
}
poly operator * (const poly& a,const poly& b) {
	if(!a.size()) return a;
	if(!b.size()) return b;
	poly c(merge_shrink(a.shrink_len,b.shrink_len));
	c.reserve(a.size()+b.size()-1);
	int as=min(a.size(),c.size()),
		bs=min(b.size(),c.size());
	int K=getK(as+bs-1);
	mi*da=alc(K,1),*db=alc(K,1);
	for(int i=0;i<as;++i) da[i]=a[i];
	for(int i=0;i<bs;++i) db[i]=b[i];
	fft(da,K,0); fft(db,K,0);
	for(int i=0;i<K;++i) da[i]=da[i]*db[i];
	fft(da,K,1);
	for(int i=0;i<c.size();++i) c[i]=da[i];
	pt-=K*2;
	return c;
}
//(quotient, remainder)
pair<poly,poly> gdiv(poly a,poly b) {
	assert(a.is_poly()&&b.is_poly());
	int n=a.size(),m=b.size(); assert(m>0);
	if(n<m)
		return make_pair(poly(-1),a);
	poly d(-1),r(-1); d.reserve(n-m+1); r.reserve(m-1);
	gdiv(a.coeff_ptr(),b.coeff_ptr(),d.coeff_ptr(),r.coeff_ptr(),n,m);
	return make_pair(d,r);
}
poly gint(poly a) {
	a.reserve(a.size()+1);
	for(int i=a.size()-1;i>=1;--i)
		a[i]=a[i-1]*rfac[i]*fac[i-1];
	if(a.size()) a[0]=0;
	return a;
}
//note: this actually decreases shrink!
poly gde(poly a) {
	if(!a.size()) return a;
	for(int i=1;i<a.size();++i)
		a[i-1]=a[i]*i;
	a[a.size()-1]=0;
	a.clean_maybe();
	return a;
}
//solve G(f)=0
poly gnewton(
	function<poly(const poly&)> g,
	function<poly(const poly&)> gp,
	int f0,int len=default_shrink) {
	poly f(1); f[0]=f0;
	while(f.shrink_len!=len) {
		int old_len=f.shrink_len;
		int new_len=min(old_len*2,len);
		f.set_shrink(new_len);
		poly s=g(f); s.fit_shrink();
		poly h=f;
		h.set_shrink(new_len-old_len);
		h=ginv(gp(h));
		s.coeff.erase(s.coeff.begin(),s.coeff.begin()+old_len);
		s.set_shrink(new_len-old_len);
		s=h*s; s.set_shrink(new_len);
		s.coeff.insert(s.coeff.begin(),old_len,mi(0));
		f=f-s;
	}
	return f;
}
//find [x^n](a(x)/b(x))
mi linear_eval(poly a,poly b,ll n) {
	assert(a.is_poly()&&b.is_poly()&&b.size()>=1);
	while(n) {
		poly nb=b;
		for(int i=1;i<nb.size();i+=2)
			nb[i]=-nb[i];
		auto clip=[&](poly p) {
			p.reserve(1);
			int u=p.size()-1;
			for(int i=1;i<=u/2;++i)
				p[i]=p[i+i];
			p.coeff.resize(u/2+1);
			return p;
		};
		poly s=a*nb,t=b*nb;
		if(n&1)
			s.reserve(1),s.coeff.erase(s.coeff.begin());
		a=clip(s); b=clip(t);
		n>>=1;
	}
	return a.get(0)*inv(b.get(0));
}
vector<mi> BM(vector<mi> x) {
	vector<mi> ls,cur;
	int lf=0; mi ldt;
	for(int i=0;i<int(x.size());++i) {
		mi t=-x[i];
		for(int j=0;j<int(cur.size());++j)
			t=t+x[i-j-1]*cur[j];
		if(t==0) continue;
		if(!cur.size()) {
			cur.resize(i+1); lf=i; ldt=t; continue;
		}
		mi k=-t*inv(ldt);
		vector<mi> c(i-lf-1); c.pb(-k);
		for(int j=0;j<int(ls.size());++j) c.pb(ls[j]*k);
		if(c.size()<cur.size()) c.resize(cur.size());
		for(int j=0;j<int(cur.size());++j)
			c[j]=c[j]+cur[j];
		if(i-lf+(int)ls.size()>=(int)cur.size())
			ls=cur,lf=i,ldt=t;
		cur=c;
	}
	return cur;
}
pair<poly,poly> bm_poly(vector<mi> x) {
	vector<mi> f=BM(x); int k=f.size();
	f.insert(f.begin(),mi(-1)); x.resize(k);
	poly r(f,-1),s(x,-1);
	poly u=r*s; u.coeff.resize(k);
	return make_pair(u,r);
}
mi linear_eval(vector<mi> x,ll n) {
	auto s=bm_poly(x);
	return linear_eval(s.first,s.second,n);
}
vector<poly> eval_tmp;
void eval_build(int x,mi*a,int n) {
	if((int)eval_tmp.size()<x+1) eval_tmp.resize(x+1);
	if(n==1) {
		eval_tmp[x]=poly(vector<mi>{mi(1),-*a},-1);
		return;
	}
	int m=(n+1)>>1;
	eval_build(x+x,a,m);
	eval_build(x+x+1,a+m,n-m);
	eval_tmp[x]=eval_tmp[x+x]*eval_tmp[x+x+1];
}
//transposed multiplication
poly mul_transpose(const poly& a,const poly& b) {
	assert(a.is_poly()&&b.size()>0&&b.is_poly());
	if(a.size()<b.size()) return poly(-1);
	poly c(-1);
	c.reserve(a.size()-b.size()+1);
	int K=getK(a.size());
	mi*da=alc(K,1),*db=alc(K,1);
	for(int i=0;i<a.size();++i) da[i]=a[i];
	for(int i=0;i<b.size();++i) db[i]=b[b.size()-1-i];
	fft(da,K,0); fft(db,K,0);
	for(int i=0;i<K;++i) da[i]=da[i]*db[i];
	fft(da,K,1);
	for(int i=0;i<c.size();++i) c[i]=da[i+b.size()-1];
	pt-=K*2;
	return c;
}
void eval_recurse(int x,poly p,mi*o,int n) {
	if(n==1) {
		*o=p.get(0);
		return;
	}
	int m=(n+1)>>1;
	eval_recurse(x+x,mul_transpose(p,eval_tmp[x+x+1]),o,m);
	eval_recurse(x+x+1,mul_transpose(p,eval_tmp[x+x]),o+m,n-m);
}
vector<mi> multipoint_eval(poly p,vector<mi> q) {
	assert(p.is_poly());
	if(!q.size()) return q;
	eval_build(1,q.data(),q.size());
	int d=p.size(); p.set_shrink(d); p.rev();
	poly o=eval_tmp[1]; o.set_shrink(d);
	p=p*ginv(o); p.rev();
	p.set_shrink(-1); p.coeff.resize(q.size());
	vector<mi> s(q.size());
	eval_recurse(1,p,s.data(),q.size());
	eval_tmp.clear(); return s;
}
vector<poly> interp_tmp;
vector<mi> interp_y;
void interp_build(int x,mi*a,int n) {
	if((int)interp_tmp.size()<x+1) interp_tmp.resize(x+1);
	if(n==1) {
		interp_tmp[x]=poly(vector<mi>{-*a,mi(1)},-1);
		return;
	}
	int m=(n+1)>>1;
	interp_build(x+x,a,m);
	interp_build(x+x+1,a+m,n-m);
	interp_tmp[x]=interp_tmp[x+x]*interp_tmp[x+x+1];
}
poly interp_calc(int x,int o,int n) {
	if(n==1)
		return poly(vector<mi>{interp_y[o]},-1);
	int m=(n+1)>>1;
	return
		 interp_calc(x+x,o,m)*interp_tmp[x+x+1]
		+interp_calc(x+x+1,o+m,n-m)*interp_tmp[x+x];
}
poly multipoint_interp(vector<mi> x,vector<mi> y) {
	assert(x.size()==y.size());
	interp_build(1,x.data(),x.size());
	interp_y=multipoint_eval(gde(interp_tmp[1]),x);
	for(int i=0;i<(int)y.size();++i)
		interp_y[i]=y[i]*inv(interp_y[i]);
	poly ans=interp_calc(1,0,x.size());
	interp_tmp.clear();
	interp_y.clear(); return ans;
}
poly gpow(poly p,string k) {
	int u=p.shrink_len,x=0;
	p.fit_shrink();
	while(x<u&&p[x]==0) ++x;
	double kd=0; mi m0=0; ll m1=0;
	for(char c:k) {
		kd=kd*10+c-48;
		m0=m0*10+int(c-48);
		m1=(m1*10+int(c-48))%(MOD-1);
	}
	if(x==u||x*kd>=u*2) return poly(u);
	p.coeff.erase(p.coeff.begin(),p.coeff.begin()+x);
	mi v=p[0],s=qp(v,m1),iv=inv(v);
	for(mi&w:p.coeff) w=w*iv;
	p=gexp(m0*gln(p));
	for(mi&w:p.coeff) w=w*s;
	p.coeff.insert(p.coeff.begin(),x*m1,mi(0));
	p.fit_shrink(); return p;
}
poly gpow(poly p,ll k) {
	return gpow(p,to_string(k));
}
poly powersum_recurse(mi*a,int n) {
	if(n==1) return poly({mi(1),-*a},-1);
	int m=n>>1;
	return powersum_recurse(a,m)*
		powersum_recurse(a+m,n-m);
}
vector<mi> powersum(vector<mi> x,int n) {
	poly s=powersum_recurse(x.data(),x.size());
	s.set_shrink(n); poly t=s;
	for(int i=0;i<=(int)x.size()&&i<t.size();++i)
		t[i]=t[i]*((int)x.size()-i);
	poly w=t*ginv(s);
	vector<mi> o(n);
	for(int i=0;i<n;++i) o[i]=w.get(i);
	return o;
}
poly PMSet(poly p,bool s) {
	p.fit_shrink();
	assert(p.get(0)==0);
	poly q(p.shrink_len);
	q.fit_shrink();
	for(int i=1;i<p.size();++i) {
		mi iv=rfac[i]*fac[i-1];
		if(!(i&1)&&s) iv=-iv;
		for(int j=1;i*j<p.size();++j)
			q[i*j]=q[i*j]+p[j]*iv;
	}
	return gexp(q);
}
poly MSet(poly p) {return PMSet(p,0);}
poly PSet(poly p) {return PMSet(p,1);}
poly invPMSet(poly p,bool s) {
	p.fit_shrink();
	assert(p.get(0)==1);
	p=gln(p); p.fit_shrink();
	for(int i=1;i<p.size();++i) {
		for(int j=2;i*j<p.size();++j) {
			mi iv=rfac[j]*fac[j-1];
			if(!(j&1)&&s) iv=-iv;
			p[i*j]=p[i*j]-p[i]*iv;
		}
	}
	return p;
}
poly invMSet(poly p) {return invPMSet(p,0);}
poly invPSet(poly p) {return invPMSet(p,1);}
//solve f'=G(f), gp=(G,G')
poly gnewton_d(
	function<pair<poly,poly>(const poly&)> gp,
	int f0,int len=default_shrink) {
	poly f(1); f[0]=f0;
	while(f.shrink_len!=len) {
		int old_len=f.shrink_len;
		int new_len=min(old_len*2,len);
		f.set_shrink(new_len);
		auto fp=gp(f);
		poly gpf=fp.second,r=gexp(mi(-1)*gint(gpf));
		f=gint((fp.first-gpf*f)*r);
		f[0]=f0; f=f*ginv(r);
	}
	return f;
}
poly gnewton_d(
	function<poly(const poly&)> g,
	function<poly(const poly&)> gp,
	int f0,int len=default_shrink) {
	return gnewton_d([&](const poly& s) {
		return make_pair(g(s),gp(s));
	},f0,len);
}
//G^<-1>, gp=(G,G')
poly gcompinv(
	function<pair<poly,poly>(const poly&)> gp,
	int f0,int len=default_shrink) {
	poly f(1); f[0]=f0;
	while(f.shrink_len!=len) {
		int old_len=f.shrink_len;
		int new_len=min(old_len*2,len);
		f.set_shrink(new_len);
		auto fp=gp(f);
		auto gf=fp.first; gf=mi(-1)*gf;
		gf.reserve(2);++gf[1];
		f=f+gf*ginv(fp.second);
	}
	return f;
}
poly gcompinv(
	function<poly(const poly&)> g,
	function<poly(const poly&)> gp,
	int f0,int len=default_shrink) {
	return gcompinv([&](const poly& s) {
		return make_pair(g(s),gp(s));
	},f0,len);
}
poly prod_recurse(poly*a,int n) {
	if(n==1) return *a;
	int m=n>>1;
	return prod_recurse(a,m)
		*prod_recurse(a+m,n-m);
}
poly prod(vector<poly> p) {
	if(!p.size()) return poly(-1);
	sort(p.begin(),p.end(),[&](const poly&a,const poly&b) {
		return a.size()<b.size();
	}); //maybe faster?
	return prod_recurse(p.data(),p.size());
}
poly polyi(mi x) {
	return poly(vector<mi>{x},-1);
}
poly operator"" _p(unsigned long long int x) {
	return poly(vector<mi>{int(x%MOD)},-1);
}
poly operator"" _p(const char *str,std::size_t len) {
	poly ans(-1); int sgn=1,phase=0,coeff=0,touch=0;
	ll cnum=0;
	auto clean=[&]() {
		if(phase==-1) ans[1]+=sgn*coeff;
		else if(phase==0) ans[0]+=sgn*(int)cnum;
		else if(phase==1) ans[cnum]+=sgn*coeff;
		else assert(0);
		phase=0; cnum=0; touch=0;
	};
	for(int i=0;i<(int)len;++i) {
		if(str[i]=='+') clean(),sgn=1;
		else if(str[i]=='-') clean(),sgn=-1;
		else if(isdigit(str[i])) {
			assert(phase==0||phase==1);
			if(phase==0)
				touch=1,
				cnum=(cnum*10LL+str[i]-48)%MOD;
			else
				cnum=cnum*10LL+str[i]-48,
				assert(cnum<1e8);
		}
		else if(str[i]=='x') {
			assert(str[i+1]=='^'||str[i+1]=='+'||str[i+1]=='-'||str[i+1]==0);
			phase=-1; coeff=touch?cnum:1; cnum=0;
		}
		else if(str[i]=='^') {
			assert(phase==-1); phase=1;
		}
	}
	clean();
	return ans;
}
pair<poly,poly> gsincos(poly p) {
	assert(p.is_series());
	mi j=qp(mi(3),(MOD-1)/4);
	poly a=gexp(j*p),b=gexp(-j*p);
	poly s=(a-b)*inv(2*j),c=(a+b)*inv(2);
	return make_pair(s,c);
}
poly gcorner(poly a,vector<mi> b) {
	a.reserve(b.size());
	for(int i=0;i<a.size()&&i<(int)b.size();++i)
		a[i]=b[i];
	return a;
}
poly gshl(poly a,int b) {
	a.coeff.insert(a.coeff.begin(),b,mi(0));
	a.shrink(); return a;
}
poly gshr(poly a,int b) {
	if(a.size()<b) a.coeff.clear();
	else a.coeff.erase(a.coeff.begin(),a.coeff.begin()+b);
	a.shrink(); return a;
}
//A(x)=a(x^u)
poly gamp(const poly& a,int u) {
	assert(a.is_series()&&u>=1);
	poly b(a.shrink_len);
	for(int i=0;i*u<a.shrink_len;++i)
		b[i*u]=a[i];
	return b;
}
poly operator - (poly a) {
	for(auto&s:a.coeff) s=-s;
	return a;
}


namespace onlineconv {
struct ocpoly {
	function<mi(int)> get_handle;
	vector<int> vis;
	vector<mi> val;
	string typ; //debug purpose
	mi get(int x) {
//		cerr<<"debug: get("<<x<<") ("<<this<<","<<typ<<")\n";
		assert(x>=0);
		if((int)vis.size()>x&&vis[x]) return val[x];
		if((int)vis.size()<=x)
			vis.resize(x+1),val.resize(x+1);
		val[x]=get_handle(x); vis[x]=1; return val[x];
	}
	poly await(int n) {
		poly s(-1);
		for(int i=0;i<n;++i)
			s[i]=get(i);
		return s;
	}
	void copy(ocpoly*b) {
		if(typ=="") typ="copier";
		get_handle=[=](int c) {
			return b->get(c);
		};
	}
	ocpoly() {}
	ocpoly(ocpoly const&) = delete;
	ocpoly& operator = (ocpoly const&) = delete;
};
struct ocint: public ocpoly {
	ocint(ocpoly*p,mi c=0) {
		typ="integ";
		get_handle=[=](int u) {
			if(u==0) return c;
			return p->get(u-1)*rfac[u]*fac[u-1];
		};
	}
};
struct ocde: public ocpoly {
	ocde(ocpoly*p) {
		typ="deriv";
		get_handle=[=](int u) {
			return p->get(u+1)*mi(u+1);
		};
	}
};
struct ocshr: public ocpoly {
	ocshr(ocpoly*p,int c) {
		typ="shiftr";
		assert(c>=0);
		get_handle=[=](int u) {
			return p->get(u+c);
		};
	}
};
struct ocshl: public ocpoly {
	ocshl(ocpoly*p,int c) {
		typ="shiftl";
		assert(c>=0);
		get_handle=[=](int u) {
			if(u<c) return mi(0);
			return p->get(u-c);
		};
	}
};
struct ocscale: public ocpoly {
	ocscale(ocpoly*p,mi c) {
		typ="scale";
		get_handle=[=](int u) {
			return p->get(u)*c;
		};
	}
};
struct ocadd: public ocpoly {
	ocadd(ocpoly*a,ocpoly*b) {
		typ="add";
		get_handle=[=](int u) {
			return a->get(u)+b->get(u);
		};
	}
};
struct ocminus: public ocpoly {
	ocminus(ocpoly*a,ocpoly*b) {
		typ="minus";
		get_handle=[=](int u) {
			return a->get(u)-b->get(u);
		};
	}
};
struct ocfixed: public ocpoly {
	ocfixed(const poly&p) {
		typ="fixed";
		get_handle=[=](int u) {
			return p.get(u);
		};
	}
};
struct occorner: public ocpoly {
	occorner(ocpoly*p,vector<mi> v) {
		typ="corner";
		get_handle=[=](int u) {
			if(u<(int)v.size()) return v[u];
			return p->get(u);
		};
	}
};
mi pool1[PS2],*ptr1=pool1;
mi*alc1(int t,bool c=0) {
	if(c) cp(ptr1,0,t);
	ptr1+=t; assert(ptr1<pool1+PS2);
	return ptr1-t;
}
struct ocmul: public ocpoly {
	//fully-relaxed convultion!
	//try to put 0 on a if possible
	ocmul(ocpoly*a,ocpoly*b) {
		typ="mul";
		int&oaf=*new int(),&obf=*new int(),
		&oa=*new int(),&ob=*new int(),
		&cm=*new int(),&cpool=*new int();
		oaf=obf=oa=ob=cm=cpool=0;
		poly&cp=*new poly(-1);
		vector<pair<pair<mi*,mi*>,int>> &st
			=*new vector<pair<pair<mi*,mi*>,int>>();
		vector<pair<pair<mi*,mi*>,int>> &fa=
			*new vector<pair<pair<mi*,mi*>,int>>();
		vector<mi> &pool=*new vector<mi>();
		mi*sa=new mi[128],*sb=new mi[128],
		*la=new mi[128],*lb=new mi[128];
		get_handle=[=,&oa,&ob,&oaf,&obf,&cm,&cp,&st,&fa,&pool,&cpool]
		(int u) {
			if(u) this->get(u-1); //necessary for ocmul
			auto alc0=[&](int s) {
				//ok I hate memory management
				if(cpool+s>(int)pool.size()) {
					auto od=pool.data();
					pool.resize(max(cpool+s,(int)pool.size()*2));
					auto dt=pool.data()-od;
					if(dt) for(auto&x:st)
						if(x.first.first)
							x.first.first+=dt,
							x.first.second+=dt;
				}
				assert(cpool+s<=(int)pool.size());
				mi*ptr=pool.data()+cpool;
				::cp(ptr,0,s); cpool+=s; return ptr;
			};
			auto cnt_bk=[&](int x) {
				int ans=0;
				for(int j=(int)st.size()-1;j>=0;--j)
					if(st[j].second==x) ++ans; else break;
				return ans;
			};
			auto st_pop=[&]() {
				if(st.back().first.first)
					cpool-=st.back().second*4;
				assert(cpool>=0);
				st.pop_back();
			};
//			cerr<<u<<":"<<oa<<","<<ob<<"\n"; //debug
			//this is where deadlock usually happens..
			while(u>=oa+ob&&!(oaf&&obf)) {
				if((oa<=ob&&!oaf)||obf) {
					assert(!oaf);
					if(oa>u) break;
					if(a->get(oa)==0) ++oa;
					else oaf=1;
				}
				else {
					assert(!obf);
					if(ob>u) break;
					if(b->get(ob)==0) ++ob;
					else obf=1;
				}
			}
			if(u<oa+ob) return mi(0);
			assert(oaf&&obf); u-=oa+ob;
			#define ga(x) (a->get((x)+oa))
			#define gb(x) (b->get((x)+ob))
			la[u&127]=ga(u), lb[u&127]=gb(u);
			if(u<128) sa[u]=ga(u), sb[u]=gb(u);
			if(u==0) cp[0]+=sa[0]*sb[0];
			else cp[u]+=sa[0]*lb[u&127]+la[u&127]*sb[0];
			if((cm+1)*2<=u) {
				poly p(-1),q(-1);
				p.reserve(u+1); q.reserve(u+1);
				for(int i=0;i<=u;++i) p[i]=ga(i);
				for(int i=0;i<=u;++i) q[i]=gb(i);
				while(st.size()) st_pop();
				cp=p*q; cm=u;
			}
			//for i+j=u, at least one of [i,j] is <=cm
			if(u>cm&&u!=cm*2+1) {
				auto gfa=[&](int cu,int of,int cs) {
					int id=cu*4+of;
					if((int)fa.size()<id+1)
						fa.resize(id+1,make_pair(pair<mi*,mi*>(0,0),0));
					if(fa[id].second) {
						assert(fa[id].second==cs);
						return fa[id].first;
					}
					fa[id].second=cs;
					mi*da=alc1(cs+cs,1),*db=alc1(cs+cs,1);
					for(int i=0;i<cs;++i)
						da[i]=ga(i+cs*of),db[i]=gb(i+cs*of);
					fft(da,cs+cs,0); fft(db,cs+cs,0);
					return fa[id].first=make_pair(da,db);
				};
				int cs=1,cu=0;
				while(cnt_bk(cs)==3)
					st_pop(),st_pop(),st_pop(),cs*=4,++cu;
				//[u-cs+1,u]
				assert(getK(cs)==cs);
				if(cs>=64) {
					mi*da=alc0(cs+cs+cs+cs),*db=da+(cs+cs);
					for(int i=0;i<cs;++i)
						da[i]=ga(u-cs+1+i),db[i]=gb(u-cs+1+i);
					fft(da,cs+cs,0); fft(db,cs+cs,0);
					st.push_back(make_pair(make_pair(da,db),cs));
				}
				else
					st.push_back(make_pair(pair<mi*,mi*>(0,0),cs));
				int c=cnt_bk(cs); assert(c>=1&&c<=3);
				if(cs>=64) {
					mi*tg=alc(cs+cs,1); int l=st.size();
					for(int i=0;i<c;++i) {
						auto cur=st[l-c+i];
						int bd=c-i-1; //in [0,2]
						pair<mi*,mi*> fbd=gfa(cu,bd,cs);
						for(int j=0;j<cs+cs;++j)
							tg[j]+=cur.first.first[j]*fbd.second[j]
								+cur.first.second[j]*fbd.first[j];
						fbd=gfa(cu,bd+1,cs);
						for(int j=0;j<cs+cs;++j)
							tg[j]+=((j&1)?mi(-1):mi(1))
								*(cur.first.first[j]*fbd.second[j]
								+cur.first.second[j]*fbd.first[j]);
					}
					fft(tg,cs+cs,1);
					for(int i=cs;i<cs+cs;++i)
						cp[i-cs+u+1]+=tg[i];
					pt-=cs+cs;
				}
				else {
					int l=u-cs*c+1,r=min(cm*2+1,u+cs);
					assert(r-l+1<128);
					static mi ta[128],tb[128];
					mi*pa=ta-l,*pb=tb-l;
					for(int i=l;i<=u;++i)
						pa[i]=la[i&127],pb[i]=lb[i&127];
					for(int i=u+1;i<=r;++i) {
						ull sum=0;
						int j=l;
						for(;j+7<=u;j+=8) {
							#define par(s) \
								(ull)pa[j+s].w*sb[i-j-s].w\
								+(ull)pb[j+s].w*sa[i-j-s].w
							sum+=par(0)+par(1)+par(2)+par(3)\
								+par(4)+par(5)+par(6)+par(7);
							sum%=MOD;
						}
						for(;j<=u;++j) {
							sum+=(ull)pa[j].w*sb[i-j].w
								+(ull)pb[j].w*sa[i-j].w;
						}
						cp[i]+=int(sum%MOD);
					}
				}
			}
			#undef ga
			#undef gb
			return cp.get(u);
		};
	}
};
struct ocexp: public ocpoly {
	ocexp(ocpoly*a) {
		typ="exp";
		ocpoly*tmp=new ocpoly();
		tmp->typ="exp_helper";
		tmp->get_handle=[=](int u) {
			if(u==0) return mi(0);
			return a->get(u)*u;
		};
		ocmul*m=new ocmul(tmp,this);
		get_handle=[=](int u) {
			if(u==0) return mi(1);
			return m->get(u)*rfac[u]*fac[u-1];
		};
	}
};
struct ocmpsetp: public ocpoly {
	//mpset without exp
	ocmpsetp(ocpoly*a,bool s) {
		typ="mpset1";
		vector<mi> &tmp=*new vector<mi>();
		tmp.push_back(0);
		get_handle=[=,&tmp](int u) {
			if(u) this->get(u-1); //necessary
			int l=u;
			if(u>=(int)tmp.size()) {
				l=1; int ns=tmp.size()*2;
				tmp.clear();tmp.resize(ns);
			}
			for(int j=l;j<=u;++j) {
				mi v=a->get(j);
				if(j==0) assert(v==0);
				if(v==0) continue;
				for(int i=1;i*j<(int)tmp.size();++i) {
					mi iv=rfac[i]*fac[i-1];
					if(!(i&1)&&s) iv=-iv;
					tmp[i*j]+=iv*v;
				}
			}
			return tmp[u];
		};
	}
};
struct ocinvmpsetp: public ocpoly {
	//invmpset without ln
	ocinvmpsetp(ocpoly*a,bool s) {
		typ="invmpset1";
		vector<mi> &tmp=*new vector<mi>();
		tmp.push_back(0);
		get_handle=[=,&tmp](int u) {
			if(u) this->get(u-1); //necessary
			int l=u;
			if(u>=(int)tmp.size()) {
				l=1; int ns=tmp.size()*2;
				tmp.clear();tmp.resize(ns);
			}
			for(int j=l;j<=u;++j) {
				mi v=a->get(j)-tmp[j];
				if(j==0) assert(v==0);
				if(v==0) continue;
				for(int i=2;i*j<(int)tmp.size();++i) {
					mi iv=rfac[i]*fac[i-1];
					if(!(i&1)&&s) iv=-iv;
					tmp[i*j]+=iv*v;
				}
			}
			return a->get(u)-tmp[u];
		};
	}
};
struct ocmset: public ocpoly {
	ocmset(ocpoly*a) {
		typ="mset";
		copy(new ocexp(new ocmpsetp(a,0)));
	}
};
struct ocpset: public ocpoly {
	ocpset(ocpoly*a) {
		typ="pset";
		copy(new ocexp(new ocmpsetp(a,1)));
	}
};
struct ocinv: public ocpoly {
	ocinv(ocpoly*a) {
		typ="inv";
		mi &oi=*new mi();
		ocpoly *s=new ocmul(new occorner(a,vector<mi>{0}),this);
		get_handle=[=,&oi](int u) {
			if(!u) return oi=inv(a->get(0));
			this->get(0); return s->get(u)*(-oi);
		};
	}
};
struct ocsqrt: public ocpoly {
	ocsqrt(ocpoly*a,mi f0=1) {
		typ="sqrt"; mi c=inv(f0*2);
		ocpoly *g=new occorner(this,vector<mi>{0});
		ocpoly *s=new ocminus(a,new ocmul(g,g));
		get_handle=[=](int u) {
			if(!u) {
				mi w=s->get(u);
				assert(f0*f0==w);
				return f0;
			}
			return s->get(u)*c;
		};
	}
};
struct ocquo: public ocpoly {
	ocquo(ocpoly*a,ocpoly*b) {
		typ="quo";
		mi &oi=*new mi();
		ocpoly *s=new ocminus(a,
			new ocmul(new occorner(b,vector<mi>{0}),this));
		get_handle=[=,&oi](int u) {
			if(!u) return s->get(0)*(oi=inv(b->get(0)));
			this->get(0); return s->get(u)*oi;
		};
	}
};
struct ocln: public ocpoly {
	ocln(ocpoly*a) {
		typ="ln";
		copy(new ocint(new ocquo(new ocde(a),a)));
	}
};
struct ocinvmset: public ocpoly {
	ocinvmset(ocpoly*a) {
		typ="invmset";
		copy(new ocinvmpsetp(new ocln(a),0));
	}
};
struct ocinvpset: public ocpoly {
	ocinvpset(ocpoly*a) {
		typ="invpset";
		copy(new ocinvmpsetp(new ocln(a),1));
	}
};
struct ocpow: public ocpoly {
	ocpow(ocpoly*a,string k) {
		typ="pow";
		mi m0=0; ll m1=0,m2=0;
		for(auto c:k)
			m0=m0*10+int(c-48),
			m1=(m1*10+c-48)%(MOD-1),
			m2=min(m2*10+c-48,ll(1e9));
		ocpoly *&s=*new ocpoly*(); s=0;
		int &pad=*new int(); pad=0;
		get_handle=[=,&pad,&s](int u) {
			if(m2==0) return (u==0)?mi(1):mi(0);
			if(u) this->get(u-1);
			if(pad==u&&a->get(u)==0) ++pad;
			if(u<pad*m2) return mi(0);
			u-=pad*m2;
			if(!u) {
				ocpoly *r=new ocshr(a,pad);
				s=new ocint(new ocquo(new ocscale(new ocmul(
					new ocde(r),new ocshr(this,pad*m2)
				),m0),r));
				return qp(r->get(0),m1);
			}
			return s->get(u);
		};
	}
	ocpow(ocpoly*a,ll k): ocpow(a,to_string(k)) {}
};
struct ocamp: public ocpoly {
	ocamp(ocpoly*a,int k) {
		typ="amp";
		get_handle=[=](int u) {
			if(u%k) return mi(0);
			return a->get(u/k);
		};
	}
};
//the rest is, well, sugar
struct pipeline {
	ocpoly*p;
	pipeline() {p=new ocpoly();}
	pipeline(ocpoly *q) {assert(q);p=q;}
	pipeline(poly s) {p=new ocfixed(s);}
	mi get(int n) {return p->get(n);}
	poly await(int n) {return p->await(n);}
	void set(pipeline q) {p->copy(q.p);}
};
pipeline operator + (pipeline a,pipeline b){return new ocadd(a.p,b.p);}
pipeline operator - (pipeline a,pipeline b){return new ocminus(a.p,b.p);}
pipeline operator * (pipeline a,pipeline b){return new ocmul(a.p,b.p);}
pipeline operator * (pipeline a,mi b){return new ocscale(a.p,b);}
pipeline operator / (pipeline a,mi b){return new ocscale(a.p,inv(b));}
pipeline gcorner(pipeline a,vector<mi> b){return new occorner(a.p,b);}
pipeline gscale(pipeline a,mi b){return new ocscale(a.p,b);}
pipeline gshl(pipeline a,int b){return new ocshl(a.p,b);}
pipeline gshr(pipeline a,int b){return new ocshr(a.p,b);}
pipeline gamp(pipeline a,int b){return new ocamp(a.p,b);}
pipeline gde(pipeline a){return new ocde(a.p);}
pipeline gint(pipeline a){return new ocint(a.p);}
pipeline ginv(pipeline a){return new ocinv(a.p);}
pipeline gexp(pipeline a){return new ocexp(a.p);}
pipeline gln(pipeline a){return new ocln(a.p);}
pipeline gpow(pipeline a,string k){return new ocpow(a.p,k);}
pipeline gpow(pipeline a,ll k){return gpow(a,to_string(k));}
pipeline gquo(pipeline a,pipeline b){return new ocquo(a.p,b.p);}
pipeline gsqrt(pipeline a,mi f0=mi(1)){return new ocsqrt(a.p,f0);}
pipeline PSet(pipeline a){return new ocpset(a.p);}
pipeline MSet(pipeline a){return new ocmset(a.p);}
pipeline invPSet(pipeline a){return new ocinvpset(a.p);}
pipeline invMSet(pipeline a){return new ocinvmset(a.p);}
pipeline operator - (pipeline a){return new ocscale(a.p,mi(-1));}
}
using namespace onlineconv;

/*
int n,m,f[123456];
int main() {
	scanf("%d%d",&n,&m); ++n;
	for(int i=0;i<n;++i) scanf("%d",f+i);
	pipeline p(vector<int>(f,f+n));
	p=p-gexp(gint(ginv(gsqrt(p,mod_sqrt(f[0],MOD)))));
	p=gcorner(gln(gcorner(p,{1})),{1});
	gde(gexp(gln(p)*m)).await(n).print_len(n-1,'\n');
}
*/


int main() {
  int N;
  for (; ~scanf("%d", &N); ) {
    pipeline f0, f1;
    f0.set(gshl((gexp(f1) - gexp(f0 * f1)) * ginv("1"_p - f0), 1));
    f1.set(gshl((gexp(f1) - f0 * f0 * gexp(f0 * f1)) * ginv("1"_p - f0), 1));
    const auto ans = (f0 + f1).await(N + 1);
// for(int n=0;n<=N;++n)cerr<<(fac[n]*ans[n])<<" ";cerr<<endl;
    printf("%u\n", (fac[N] * ans[N]).w);
  }
  return 0;
}

这程序好像有点Bug,我给组数据试试?

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 3ms
memory: 92640kb

input:

1

output:

1

result:

ok 1 number(s): "1"

Test #2:

score: 0
Accepted
time: 3ms
memory: 100832kb

input:

3

output:

24

result:

ok 1 number(s): "24"

Test #3:

score: 0
Accepted
time: 4ms
memory: 99812kb

input:

5

output:

3190

result:

ok 1 number(s): "3190"

Test #4:

score: 0
Accepted
time: 7ms
memory: 100364kb

input:

100

output:

413875584

result:

ok 1 number(s): "413875584"

Test #5:

score: 0
Accepted
time: 4ms
memory: 92540kb

input:

1

output:

1

result:

ok 1 number(s): "1"

Test #6:

score: 0
Accepted
time: 4ms
memory: 92996kb

input:

2

output:

4

result:

ok 1 number(s): "4"

Test #7:

score: 0
Accepted
time: 10ms
memory: 99728kb

input:

3

output:

24

result:

ok 1 number(s): "24"

Test #8:

score: 0
Accepted
time: 3ms
memory: 100712kb

input:

4

output:

236

result:

ok 1 number(s): "236"

Test #9:

score: 0
Accepted
time: 3ms
memory: 99708kb

input:

5

output:

3190

result:

ok 1 number(s): "3190"

Test #10:

score: 0
Accepted
time: 8ms
memory: 100756kb

input:

6

output:

55182

result:

ok 1 number(s): "55182"

Test #11:

score: 0
Accepted
time: 8ms
memory: 100524kb

input:

7

output:

1165220

result:

ok 1 number(s): "1165220"

Test #12:

score: 0
Accepted
time: 7ms
memory: 99368kb

input:

8

output:

29013896

result:

ok 1 number(s): "29013896"

Test #13:

score: 0
Accepted
time: 11ms
memory: 100324kb

input:

9

output:

832517514

result:

ok 1 number(s): "832517514"

Test #14:

score: 0
Accepted
time: 17ms
memory: 101336kb

input:

10

output:

96547079

result:

ok 1 number(s): "96547079"

Test #15:

score: 0
Accepted
time: 7ms
memory: 101000kb

input:

11

output:

296100513

result:

ok 1 number(s): "296100513"

Test #16:

score: 0
Accepted
time: 10ms
memory: 99432kb

input:

12

output:

672446962

result:

ok 1 number(s): "672446962"

Test #17:

score: 0
Accepted
time: 10ms
memory: 101304kb

input:

13

output:

986909297

result:

ok 1 number(s): "986909297"

Test #18:

score: 0
Accepted
time: 8ms
memory: 101080kb

input:

14

output:

306542229

result:

ok 1 number(s): "306542229"

Test #19:

score: 0
Accepted
time: 4ms
memory: 101308kb

input:

15

output:

8548107

result:

ok 1 number(s): "8548107"

Test #20:

score: 0
Accepted
time: 7ms
memory: 100304kb

input:

16

output:

773960239

result:

ok 1 number(s): "773960239"

Test #21:

score: 0
Accepted
time: 10ms
memory: 99548kb

input:

17

output:

611627547

result:

ok 1 number(s): "611627547"

Test #22:

score: 0
Accepted
time: 4ms
memory: 100004kb

input:

18

output:

91793980

result:

ok 1 number(s): "91793980"

Test #23:

score: 0
Accepted
time: 8ms
memory: 100016kb

input:

19

output:

689202618

result:

ok 1 number(s): "689202618"

Test #24:

score: 0
Accepted
time: 12ms
memory: 99908kb

input:

20

output:

605957782

result:

ok 1 number(s): "605957782"

Test #25:

score: 0
Accepted
time: 66ms
memory: 105920kb

input:

10000

output:

713782215

result:

ok 1 number(s): "713782215"

Test #26:

score: 0
Accepted
time: 135ms
memory: 111920kb

input:

20000

output:

337916836

result:

ok 1 number(s): "337916836"

Test #27:

score: 0
Accepted
time: 178ms
memory: 115956kb

input:

30000

output:

580803285

result:

ok 1 number(s): "580803285"

Test #28:

score: 0
Accepted
time: 275ms
memory: 121556kb

input:

40000

output:

732660392

result:

ok 1 number(s): "732660392"

Test #29:

score: 0
Accepted
time: 353ms
memory: 127396kb

input:

50000

output:

660835595

result:

ok 1 number(s): "660835595"

Test #30:

score: 0
Accepted
time: 414ms
memory: 130896kb

input:

60000

output:

323452070

result:

ok 1 number(s): "323452070"

Test #31:

score: 0
Accepted
time: 539ms
memory: 138744kb

input:

70000

output:

307315915

result:

ok 1 number(s): "307315915"

Test #32:

score: 0
Accepted
time: 587ms
memory: 141340kb

input:

80000

output:

951757567

result:

ok 1 number(s): "951757567"

Test #33:

score: 0
Accepted
time: 655ms
memory: 142972kb

input:

90000

output:

426123208

result:

ok 1 number(s): "426123208"

Test #34:

score: 0
Accepted
time: 733ms
memory: 158888kb

input:

100000

output:

827418228

result:

ok 1 number(s): "827418228"

Test #35:

score: 0
Accepted
time: 787ms
memory: 153904kb

input:

110000

output:

541614559

result:

ok 1 number(s): "541614559"

Test #36:

score: 0
Accepted
time: 865ms
memory: 156880kb

input:

120000

output:

184688986

result:

ok 1 number(s): "184688986"

Test #37:

score: 0
Accepted
time: 929ms
memory: 159272kb

input:

130000

output:

898089371

result:

ok 1 number(s): "898089371"

Test #38:

score: 0
Accepted
time: 1113ms
memory: 180704kb

input:

140000

output:

949540221

result:

ok 1 number(s): "949540221"

Test #39:

score: 0
Accepted
time: 1205ms
memory: 183204kb

input:

150000

output:

767689851

result:

ok 1 number(s): "767689851"

Test #40:

score: 0
Accepted
time: 1226ms
memory: 178548kb

input:

160000

output:

553494563

result:

ok 1 number(s): "553494563"

Test #41:

score: 0
Accepted
time: 1292ms
memory: 187944kb

input:

170000

output:

270711750

result:

ok 1 number(s): "270711750"

Test #42:

score: 0
Accepted
time: 1358ms
memory: 190880kb

input:

180000

output:

108155689

result:

ok 1 number(s): "108155689"

Test #43:

score: 0
Accepted
time: 1421ms
memory: 193184kb

input:

190000

output:

327542856

result:

ok 1 number(s): "327542856"

Test #44:

score: 0
Accepted
time: 1649ms
memory: 209196kb

input:

200000

output:

236144151

result:

ok 1 number(s): "236144151"

Test #45:

score: 0
Accepted
time: 1645ms
memory: 208600kb

input:

198798

output:

16935264

result:

ok 1 number(s): "16935264"

Extra Test:

score: 0
Extra Test Passed