T83311 [concert] road ten million
answer
Comprehension surface
This is to give the operator the n-1 order of arrangement, ans statistical number t true for the program, the program to false ans statistical number F,
Seeking t / (t + f) (mod 998244535)
Thinking
Finally, consider the operator that the operator, then there are n-1 choices
(1) Last count &: ans is true: left and right key items at the same time true
ans is false: true left and right false, false left and right true, left and right false false
(2) the last count |: ans is true: left and right key items at the same time as true, the left and right true false, false left and right true
ans is false: the left and right false false
(3) The last count ^: ans is true: different left and right, left and right false true, false left and right true
ans is false: about the same, left true true and right, left and right false false
Application of the principle of multiplication and addition step statistical principles
SOLVE
note
Dividing the rearmost converted into the multiplicative inverse
Code
#include<bits/stdc++.h> using namespace std; const int mod=998244353; int n; long long ans; char s[505],opr[505]; //s存操作状态(t或f),opr存操作符(&,|,^) long long t[505][505],f[505][505]; //t存值为true的方案数,f存值为false的方案数 inline int read1() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } inline char read2() { char c; do { c=getchar(); }while(c==' '||c=='\n'||c=='\0'||c=='\t'||c=='\r'); } pair<long long,long long> extgcd(long long a,long long b) //拓展欧几里得求逆元 { if(b==0) { return make_pair<long long,long long>(1,0); } pair<long long,long long>ans=extgcd(b,a%b); ans.first^=ans.second^=ans.first^=ans.second; ans.second-=a/b*ans.first; return ans; } int main() { n=read1(); for(int i=1;i<n;i++) { s[i]=read2(); opr[i]=read2(); } s[n]=read2(); for(int i=1;i<=n;i++) //长度为1直接判断 { if(s[i]=='t') t[i][i]=1,f[i][i]=0; else t[i][i]=0,f[i][i]=1; } for(int len=2;len<=n;len++) //枚举区间长 for(int i=1;i+len-1<=n;i++) //区间起始位置 { int j=i+len-1; //区间结束位置 for(int k=i;k<j;k++) //枚举最后算的运算符 ,注意这里 ,从i枚举到j-1 { if(opr[k]=='&') { t[i][j]=(t[i][j]%mod+t[i][k]*t[k+1][j]%mod)%mod; f[i][j]=(f[i][j]%mod+(f[i][k]*f[k+1][j])%mod+(t[i][k]*f[k+1][j])%mod+(f[i][k]*t[k+1][j])%mod)%mod; } if(opr[k]=='|') { f[i][j]=(f[i][j]%mod+(f[i][k]*f[k+1][j])%mod)%mod; t[i][j]=(t[i][j]%mod+(t[i][k]*t[k+1][j])%mod+(t[i][k]*f[k+1][j])%mod+(f[i][k]*t[k+1][j])%mod)%mod; } if(opr[k]=='^') //注意这里(一开始记反了QWQ) { t[i][j]=(t[i][j]%mod+(t[i][k]*f[k+1][j])%mod+f[i][k]*t[k+1][j]%mod)%mod; f[i][j]=(f[i][j]%mod+t[i][k]*t[k+1][j]%mod+f[i][k]*f[k+1][j]%mod)%mod; } } } ans=(t[1][n]*((extgcd(t[1][n]+f[1][n]%mod,mod).first%mod+mod)%mod))%mod; printf("%ld\n",ans); return 0; }