QOJ.ac
QOJ
The 2nd Universal Cup Finals is coming! Check out our event page, schedule, and competition rules!
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#116473 | #6513. Expression 3 | serene_analysis | RE | 0ms | 0kb | C++14 | 4.7kb | 2023-06-29 12:00:42 | 2023-06-29 12:00:43 |
Judging History
answer
#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];
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;
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;
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=qpow(n,mod-2,mod);
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;
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=qpow(n,mod-2,mod);
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 now=ret,oth=mul(gave.cut(2*i),selfmul(ret)).cut(2*i);
ret.sizen(2*i);
for(int j=0;j<i;j++)now[j]=2*ret[j]%mod;
for(int j=0;j<2*i;j++)ret[j]=dec(now[j],oth[j]);
}
return ret.cut(n);
}
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 lef,poly rig){
int n=lef.pol.size()+1,m=rig.pol.size()+1;
if(n<m)return lef;
lef.prev(),rig.prev();
poly dv=mul(lef.cut(n-m+1),pinv(rig,n-m+1)).cut(n-m+1);
lef.prev(),rig.prev(),dv.prev();
return dec(lef,mul(rig,dv)).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();
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;
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: 0
Dangerous Syscalls
input:
4 9 1 4 1 -+-