Road ten million

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;
}

 

Guess you like

Origin www.cnblogs.com/xiaoyezi-wink/p/11103622.html