QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#116536#6513. Expression 3serene_analysisTL 17ms68328kbC++175.2kb2023-06-29 14:40:282023-06-29 14:40:46

Judging History

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

  • [2024-02-14 13:23:19]
  • hack成功,自动添加数据
  • (/hack/531)
  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-06-29 14:40:46]
  • 评测
  • 测评结果:TL
  • 用时:17ms
  • 内存:68328kb
  • [2023-06-29 14:40:28]
  • 提交

answer

#pragma GCC optimize(3)
#include<algorithm>
#include<cstdio>
#include<vector>
const int maxn=8e5+5;
const int mod=998244353;
const int g=3,ginv=(mod+1)/g;
int inv[maxn],fact[maxn],finv[maxn];
void init(){
	inv[0]=inv[1]=fact[0]=fact[1]=finv[0]=finv[1]=1;
	for(int i=2;i<=maxn-2;i++){
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
		fact[i]=1ll*fact[i-1]*i%mod;
		finv[i]=1ll*finv[i-1]*inv[i]%mod;
	}
	return;
}
int qpow(int a,int b,int mod){
	int ans=1;
	while(b){
		if(b&1)ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}
	return ans;
}
int rev[maxn];
void rev_init(int n,int cou){
	for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cou-1));
	return;
}
int gp[maxn],gip[maxn],pv[maxn];
void g_init(){
	int ncn=0,ts=mod-1;
	while(ts%2==0)ts/=2,ncn++;
	gp[ncn]=qpow(g,ts,mod),gip[ncn]=qpow(ginv,ts,mod),ncn--;
	while(ncn){
		gp[ncn]=1ll*gp[ncn+1]*gp[ncn+1]%mod;
		gip[ncn]=1ll*gip[ncn+1]*gip[ncn+1]%mod;
		pv[ncn]=qpow(qpow(2,ncn,mod),mod-2,mod);
		ncn--;
	}
	return;
}
int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x<y?x+mod-y:x-y;}
struct poly{
	std::vector<int>pol;
	void sizen(int k){
		pol.resize(k);
		return;
	}
	int& operator[](int x){
		if(1u*x>=pol.size())printf("std::bad_alloc,x=%d,size=%d\n",x,(int)pol.size());
		return pol.at(x);
	}
	void out(){
		int nlen=pol.size();
		for(int i=0;i<nlen;i++)printf("pol[%d]=%d\n",i,pol[i]);
		return;
	}
	void ntt(int n,int type){
		for(int i=0;i<n;i++)if(i<rev[i])std::swap(pol[i],pol[rev[i]]);
		int ncn=1;
		for(int mid=1;mid<n;mid<<=1,ncn++){
			int nr=mid*2,step=type==1?gp[ncn]:gip[ncn];
			for(int i=0;i<n;i+=nr){
				int now=1;
				for(int j=0;j<mid;j++){
					int lef=pol[i+j],rig=1ll*now*pol[i+j+mid]%mod;
					pol[i+j]=add(lef,rig),pol[i+j+mid]=dec(lef,rig);
					now=1ll*now*step%mod;
				}
			}
		}
		return;
	}
	void prev(){
		std::reverse(pol.begin(),pol.end());
		return;
	}
	poly cut(int k){
		poly ret;
		ret.sizen(k);
		int nlen=pol.size();
		for(int i=0;i<k;i++)if(i<nlen)ret[i]=pol[i];
		return ret;
	}
};
poly mul(poly now,poly oth){
	int n=now.pol.size(),m=oth.pol.size();
	poly ret;
	ret.sizen(n+m-1);
	int nlen=std::max(n,m),cou=0;
	if(nlen<=30){
		for(int i=0;i<n;i++)for(int j=0;j<m;j++)ret[i+j]=add(ret[i+j],1ll*now[i]*oth[j]%mod);
		return ret;
	}	
	m=n+m-1,n=1;
	while(n<=2*nlen)n*=2,cou++;
	rev_init(n,cou),now.sizen(n),oth.sizen(n);
	now.ntt(n,1),oth.ntt(n,1);
	for(int i=0;i<n;i++)now[i]=1ll*now[i]*oth[i]%mod;
	now.ntt(n,-1);
	int ninv=pv[cou];
	for(int i=0;i<m;i++)ret[i]=1ll*now[i]*ninv%mod;
	return ret;
}
poly selfmul(poly gave){
	int n=gave.pol.size();
	poly ret;
	ret.sizen(2*n-1);
	int nlen=n,cou=0;
	if(nlen<=30){
		for(int i=0;i<n;i++)for(int j=0;j<n;j++)ret[i+j]=add(ret[i+j],1ll*gave[i]*gave[j]%mod);
		return ret;
	}
	n=1;
	while(n<2*nlen)n*=2,cou++;
	rev_init(n,cou);
	gave.sizen(n),gave.ntt(n,1);
	for(int i=0;i<n;i++)gave[i]=1ll*gave[i]*gave[i]%mod;
	gave.ntt(n,-1);
	int ninv=pv[cou];
	for(int i=0;i<2*nlen-1;i++)ret[i]=1ll*gave[i]*ninv%mod;
	return ret;
}
poly pinv(poly gave,int n){
	poly ret;
	ret.sizen(1),ret[0]=qpow(gave[0],mod-2,mod);
	for(int i=1;i<n;i<<=1){
		poly oth=mul(gave.cut(2*i),selfmul(ret).cut(2*i)).cut(2*i);
		ret.sizen(2*i);
		for(int j=0;j<2*i;j++)ret[j]=(2u*ret[j]-oth[j]+mod)%mod;
	}
	return ret.cut(n);
}
poly pdiv(poly up,poly dw){
	int n=up.pol.size(),m=dw.pol.size();
	poly lef=up,rig=dw;
	lef.prev(),rig.prev();
	lef.sizen(n-m+1),rig.sizen(n-m+1);
	poly rinv=pinv(rig,n-m+1),ret=mul(lef,rinv).cut(n-m+1);
	ret.prev();
	return ret;
}
poly dec(poly now,poly oth){
	int nlen=now.pol.size();
	for(int i=0;i<nlen;i++)now[i]=add(now[i],mod-oth[i]);
	return now;
}
poly pmod(poly now,poly oth){
	int n=now.pol.size(),m=oth.pol.size();
	if(n<m)return now;
	poly ndiv=pdiv(now,oth);
	return dec(now,mul(oth,ndiv)).cut(m-1);
}
struct node{
	int l,r;
	poly nv,nmod;
}tree[maxn];
int a[maxn],sgn[maxn],c[maxn];
void build(int i,int l,int r){
	tree[i].l=l,tree[i].r=r;
	if(l==r){
		poly now,oth;
		now.sizen(2),oth.sizen(2),now[1]=oth[1]=1,now[0]=mod-l,oth[0]=mod-c[l];
		tree[i].nv=oth,tree[i].nmod=now;
		return;
	}
	int mid=(l+r)>>1;
	build(i*2,l,mid),build(i*2+1,mid+1,r);
	tree[i].nv=mul(tree[i*2].nv,tree[i*2+1].nv);
	tree[i].nmod=mul(tree[i*2].nmod,tree[i*2+1].nmod);
	return;
}
int ans;
void go(int i,poly gave){
	if(tree[i].l==tree[i].r){
		int ni=tree[i].l;
		(ans+=1ll*a[ni]*finv[ni-1]%mod*gave[0]%mod)%=mod;
		return;
	}
	go(i*2,pmod(gave,tree[i*2].nmod)),go(i*2+1,pmod(mul(gave,tree[i*2].nv),tree[i*2+1].nmod));
	return;
}
void test(){
	poly fir,sec;
	fir.sizen(3),sec.sizen(2),fir[0]=fir[2]=sec[0]=1,fir[1]=sec[1]=2;
	mul(fir,sec).out();
	mul(pinv(fir,3),fir).out();
	pmod(mul(fir,sec),fir).out();
	return;
}
int n;
signed main(){
	g_init(),init();
	if(1){
		scanf("%d",&n);
		for(int i=1;i<=n;i++)scanf("%d",a+i);
		scanf("\n");
		for(int i=1;i<=n-1;i++)sgn[i]=(getchar()=='+'?1:mod-1),c[i]=(i+1+mod-sgn[i])%mod;
	}
	else{
		n=2e5;
		for(int i=1;i<=n;i++)a[i]=1;
		for(int i=1;i<=n-1;i++)sgn[i]=1,c[i]=(i+1+mod-sgn[i])%mod;
	}
	poly one;
	one.sizen(1),one[0]=1;
	build(1,1,n),go(1,one);
	printf("%lld",1ll*fact[n-1]*ans%mod);
	return 0;
}
/*
4
9 1 4 1
-+-
*/
//namespace burningContract

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 11ms
memory: 68328kb

input:

4
9 1 4 1
-+-

output:

46

result:

ok 1 number(s): "46"

Test #2:

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

input:

5
1 2 3 4 5
+-+-

output:

998244313

result:

ok 1 number(s): "998244313"

Test #3:

score: -100
Time Limit Exceeded

input:

100000
664815434 205025136 871445392 797947979 379688564 336946672 231295524 401655676 526374414 670533644 156882283 372427821 700299596 166140732 677498490 44858761 185182210 559696133 813911251 842364231 681916958 114039865 222372111 784286397 437994571 152137641 650875922 613727135 209302742 5321...

output:


result: