Problem:
じゃんけん式 (Rock-Scissors-Paper Expression)
問題文
この問題では，じゃんけんの手「グー」「チョキ」「パー」をそれぞれ
R, S, P
で表す．
R
は
S
に勝ち，
S
は
P
に勝ち，
P
は
R
に勝つ．
x, y
をじゃんけんの手とするとき，
x + y, x - y, x * y
を以下のように定める (これらは通常の意味での足し算・引き算・掛け算ではない)：
x + y
は，
x ≠ y
のとき
x
と
y
のうち勝つ方とし，
x = y
のとき
x
とする．
x - y
は，
x ≠ y
のとき
x
と
y
のうち負ける方とし，
x = y
のとき
x
とする．
x * y
は，
x ≠ y
のとき
R, S, P
のうち
x
でも
y
でもないものとし，
x = y
のとき
x
とする．
じゃんけんの手と
+, -, *
と括弧からなる式は，以下のように計算する：
括弧の中は先に計算する．例えば，
R * (P + S) = R * S = P
である．
括弧の深さが同じ部分については，
+, -
より
*
の方を優先して計算する．例えば，
R - P * S = R - (P * S) = R - R = R
である．
同じ優先順位のもの (
+
どうし，
-
どうし，
+
と
-
，
*
どうし) については，左から順番に計算する．例えば，
R - P + S = (R - P) + S = R + S = R
である．
JOI さんはあるじゃんけんの式を持っていたが，その式の中の
R, S, P
の一部が見えなくなってしまった．見えなくなってしまった部分が `?' で表された長さ
N
の文字列
E
が与えられる．JOI さんは，見えなくなってしまった部分のそれぞれに
R, S, P
のいずれかを割り当てる方法であって，式の計算結果が
A
になるものが何通りあるかを知りたい．その数は非常に大きくなる可能性があるので，
1 000 000 007
で割った余りを求めたい．
本問で用いられる文法は，BNF (バッカス・ナウア記法) を用いて以下のように表される．じゃんけんの式の一部が見えなくなってしまったものは <expression> である．
<expression> ::= <term> | <expression> "+" <term> | <expression> "-" <term>
<term> ::= <factor> | <term> "*" <factor>
<factor> ::= "R" | "S" | "P" | "?" | "(" <expression> ")"
これは例えば，ある文字列が <expression> であるとは，「<term> である」または「<expression> である文字列，`+'，<term> である文字列，をこの順に連結させたもの」または「<expression> である文字列，`-'，<term> である文字列，をこの順に連結させたもの」であることである，というように再帰的に定義されることを意味する．
<expression> である文字列
E
と計算結果
A
が与えられるので，`?' に
R, S, P
のいずれかを割り当てる方法であって式の計算結果が
A
になるものの個数を
1 000 000 007
で割った余りを求めるプログラムを作成せよ．
制約
1 ≦ N ≦ 200 000
．
E
は長さ
N
の文字列である．
E
は問題文で定められた <expression> である．
A
は `R' または `S' または `P' である．
入力
入力は以下の形式で標準入力から与えられる．
N
E
A
出力
標準出力に，`?' に
R, S, P
のいずれかを割り当てる方法であって式の計算結果が
A
になるものの個数を
1 000 000 007
で割った余りを
1
行で出力せよ．
入出力例
入力例 1
11
S+?-(R+?)*P
S
出力例 1
6
2
箇所の `?' に
R, S, P
のいずれかを割り当てて計算結果を
S
にする方法は，以下の
6
通りがある：
S + R - (R + R) * P
S + R - (R + S) * P
S + S - (R + R) * P
S + S - (R + S) * P
S + P - (R + R) * P
S + P - (R + S) * P
入力例 2
15
?+?-?*?+?-?*?+?
R
出力例 2
2187
入力例 3
13
(((((R)))))+?
P
出力例 3
1
入力例 4
1
P
S
出力例 4
0
入力例 5
27
R+((?+S-?*P+?)-P*?+S-?)*R+?
P
出力例 5
381
入力例 6
83
((R+?)*(?+?))*((?+?)*(?+?))*((?+?)*(?+?))-((S+?)*(?+?))*((?+?)*(?+?))*((?+?)*(?+?))
P
出力例 6
460353133
条件を満たす割り当て方は
10 460 353 203
通りあるため，それを
1 000 000 007
で割った余りである
460 353 133
を出力する．
情報オリンピック日本委員会
作 『第 19 回日本情報オリンピック JOI 2019/2020 一次予選競技課題』

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

const ll mod=1e9+7;


vector<ll> E(char c){
    if(c=='R')return {1,0,0};
    else if(c=='S')return {0,1,0};
    else if(c=='P')return {0,0,1};
    else if(c=='?')return {1,1,1};
    else return {-1,0,0};
}

void calc(vector<ll> &A,vector<ll> &B,int type){
    if(A[0]==-1){
        swap(A,B);
        return;
    }
    vector<ll> R(3,0);
    for(int a=0;a<3;a++)for(int b=0;b<3;b++){
        if(a==b)R[a]+=(A[a]*B[b])%mod;
        else if(type==1){
            if((a==0&&b==2)||(a==2&&b==0))R[2]+=(A[a]*B[b])%mod;
            else R[min(a,b)]+=(A[a]*B[b])%mod;
        }
        else if(type==0){
            if((a==0&&b==2)||(a==2&&b==0))R[0]+=(A[a]*B[b])%mod;
            else R[max(a,b)]+=(A[a]*B[b])%mod;
        }
        else{
            R[3-a-b]+=(A[a]*B[b])%mod;
        }
    }
    for(int i=0;i<3;i++)R[i]%=mod;
    swap(A,R);
    B=E('!');
}

int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    ll N;
    string S;
    char C;
    cin>>N>>S>>C;
    
    vector<vector<ll>> P(N+1,E('!')), M(N+1,E('!'));
    vector<bool> is_plus(N+1,1);
    int level=0;
    for (int i = 0; i < N; i++) {
        if (S[i] == '(')level++;
        else if (S[i] == ')') {
            calc(P[level], M[level],is_plus[level]);
            calc(M[level-1],P[level],2);
            is_plus[level]=1;
            level--;
        }
        else if (S[i] == '+' || S[i] == '-') {
            calc(P[level],M[level],is_plus[level]);
            is_plus[level] = (S[i] == '+');
        }
        else if (S[i] == '*'){}
        else {
            vector<ll> H=E(S[i]);
            calc(M[level],H,2);
        }
    }
    calc (P[0],M[0],is_plus[0]);

    if(C=='R')cout<<P[0][0]<<endl;
    else if(C=='S')cout<<P[0][1]<<endl;
    else cout<<P[0][2]<<endl;
}
accuracy: 1
time_ms: 20
memory_kb: 25256
final_rank: 3

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cassert>
#include <chrono>
#include <random>
#include <set>
#include <utility>
#include <array>
#include <bitset>
#include <unordered_set>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

template <int mod>
struct static_modint {
    using mint = static_modint;
    int x;

    static_modint() : x(0) {}
    static_modint(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    mint& operator+=(const mint& rhs) {
        if ((x += rhs.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        if ((x += mod - rhs.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        x = (int) (1LL * x * rhs.x % mod);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint pow(long long n) const {
        mint _x = *this, r = 1;
        while (n) {
            if (n & 1) r *= _x;
            _x *= _x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const { return pow(mod - 2); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }
    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs.x == rhs.x;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs.x != rhs.x;
    }

    friend ostream &operator<<(ostream &os, const mint &p) {
        return os << p.x;
    }
    friend istream &operator>>(istream &is, mint &a) {
        int64_t t; is >> t;
        a = static_modint<mod>(t);
        return (is);
    }
};

const unsigned int mod = 1e9+7;
using modint = static_modint<mod>;
modint mod_pow(ll n, ll x) { return modint(n).pow(x); }
modint mod_pow(modint n, ll x) { return n.pow(x); }

// R,S,P
int f(char c) {
    if (c == 'R') return 0;
    else if (c == 'S') return 1;
    else if (c == 'P') return 2;
    else if (c == '?') return 3;
    else {
        assert(false);
    }
}

struct S : public array<modint,3> {
    S() {
        (*this)[0] = 0;
        (*this)[1] = 0;
        (*this)[2] = 0;
    }
    explicit S(char c) {
        int ff = f(c);
        for (int i = 0; i < 3; ++i) {
            (*this)[i] = (i == ff or ff == 3);
        }
    }

    S operator+=(const S &r) {
        S res = S();
        for (int i = 0; i < 3; ++i) {
            res[i] += (*this)[i] * r[(i+1)%3];
            res[i] += (*this)[(i+1)%3] * r[i];
            res[i] += (*this)[i] * r[i];
        }
        return *this = res;
    }
    S operator-=(const S &r) {
        S res = S();
        for (int i = 0; i < 3; ++i) {
            res[i] += (*this)[i] * r[(i+2)%3];
            res[i] += (*this)[(i+2)%3] * r[i];
            res[i] += (*this)[i] * r[i];
        }
        return *this = res;
    }
    S operator*=(const S &r) {
        S res = S();
        for (int i = 0; i < 3; ++i) {
            res[i] += (*this)[(i+2)%3] * r[(i+1)%3];
            res[i] += (*this)[(i+1)%3] * r[(i+2)%3];
            res[i] += (*this)[i] * r[i];
        }
        return *this = res;
    }

    void debug() {
        cout << (*this)[0] << " " << (*this)[1] << " " << (*this)[2] << endl;
    }
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    string s; cin >> s;
    char C; cin >> C;

    int idx = 0;
    auto slv = [&](auto slv, string &s, int &idx) -> S {
        vector<S> val;
        vector<char> op;
        while (idx < s.size()) {
            if (s[idx] == '+' or s[idx] == '-' or s[idx] == '*') {
                op.push_back(s[idx]);
                idx += 1;
            }
            else if (s[idx] == '(') {
                idx += 1;
                val.push_back(slv(slv, s, idx));
                assert(s[idx] == ')');
                idx += 1;
            }
            else if (s[idx] == ')') {
                break;
            }
            else {
                S v = S(s[idx]);
                val.push_back(v);
                idx += 1;
            }
        }
        {
            vector<S> nval = {val[0]};
            vector<char> nop;
            for (int i = 0; i < op.size(); ++i) {
                if (op[i] == '*') {
                    nval.back() *= val[i+1];
                }
                else {
                    nop.push_back(op[i]);
                    nval.push_back(val[i+1]);
                }
            }
            swap(val, nval);
            swap(op, nop);
        }
        {
            for (int i = 0; i < op.size(); ++i) {
                if (op[i] == '+') {
                    val[0] += val[i+1];
                }
                else {
                    val[0] -= val[i+1];
                }
            }
        }
//        val[0].debug();
        return val[0];
    };
    auto res = slv(slv, s, idx);
    cout << res[f(C)] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 26916
final_rank: 1

code_snippet: #include<algorithm>
#include<bitset>
#include<cassert>
#include<cfloat>
#include<climits>
#include<cmath>
#include<deque>
#include<functional>
#include<iomanip>
#include<iostream>
#include<map>
#include<numeric>
#include<queue>
#include<set>
#include<stack>
#include<string>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<vector>

using namespace std;

using lint = long long;
using P = pair<int, int>;
using LLP = pair<long long, long long>;

#define REP(i, x, n) for(int i = (x), i##_len = (int)(n) ; i < i##_len ; ++i)
#define rep(i, n) for(int i = 0, i##_len = (int)(n) ; i < i##_len ; ++i)
#define reps(i, n) for(int i = 1, i##_len = (int)(n) ; i <= i##_len ; ++i)
#define rrep(i, n) for(int i = (int)(n) - 1 ; i >= 0 ; --i)
#define rreps(i, n) for(int i = (int)(n) ; i > 0 ; --i)
#define SORT(x) sort((x).begin(), (x).end())
#define SORT_INV(x) sort((x).rbegin(), (x).rend())
#define REVERSE(x) reverse((x).begin(), (x).end())
#define TWINS(x) cout << ((x) ? "Yay!" : ":(") << '\n'

constexpr int IINF = (1 << 30) - 1;
constexpr long long LLINF = 1LL << 61;
constexpr double EPS = 1e-10;

constexpr int dx4[] = {1, 0, -1, 0}, dy4[] = {0, 1, 0, -1};
constexpr int dx8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dy8[] = {0, -1, -1, -1, 0, 1, 1, 1};

template<typename T>
bool chmax(T& a, T b){
    if(a < b){
        a = b;
        return true;
    }
    return false;
}

template<typename T>
bool chmin(T& a, T b){
    if(b < a){
        a = b;
        return true;
    }
    return false;
}

template <long long modulus>
class ModInt{
    long long num;

    constexpr long long mod(long long x) const noexcept {
        x %= modulus;
        if(x < 0){
            x += modulus;
        }
        return x;
    }

    constexpr long long inv(long long x) const noexcept {
        long long y = modulus, u = 1, v = 0;
        while(y){
            long long t = x / y;
            x -= t * y;
            std::swap(x, y);
            u -= t * v;
            std::swap(u, v);
        }
        return mod(u);
    }

public:
    constexpr ModInt(const long long x = 0) noexcept : num(mod(x)) {}

    constexpr long long &value() noexcept { return num; }

    constexpr const long long &value() const noexcept { return num; }

    constexpr ModInt operator+(const ModInt rhs) const noexcept {
        return ModInt(*this) += rhs;
    }

    constexpr ModInt operator-(const ModInt rhs) const noexcept {
        return ModInt(*this) -= rhs;
    }

    constexpr ModInt operator*(const ModInt rhs) const noexcept {
        return ModInt(*this) *= rhs;
    }

    constexpr ModInt operator/(const ModInt rhs) const noexcept {
        return ModInt(*this) /= rhs;
    }

    constexpr ModInt &operator+=(const ModInt rhs) noexcept {
        num += rhs.num;
        if (num >= modulus){
            num -= modulus;
        }
        return *this;
    }

    constexpr ModInt &operator-=(const ModInt rhs) noexcept {
        if (num < rhs.num){
            num += modulus;
        }
        num -= rhs.num;
        return *this;
    }

    constexpr ModInt &operator*=(const ModInt rhs) noexcept {
        num = num * rhs.num % modulus;
        return *this;
    }

    constexpr ModInt &operator/=(const ModInt rhs) noexcept {
        num = num * inv(rhs.num) % modulus;
        return *this;
    }

    template<typename T>
    constexpr ModInt operator+(const T rhs) const noexcept {
        return ModInt(*this) += rhs;
    }

    template<typename T>
    constexpr ModInt operator-(const T rhs) const noexcept {
        return ModInt(*this) -= rhs;
    }

    template<typename T>
    constexpr ModInt operator*(const T rhs) const noexcept {
        return ModInt(*this) *= rhs;
    }

    template<typename T>
    constexpr ModInt operator/(const T rhs) const noexcept {
        return ModInt(*this) /= rhs;
    }

    template<typename T>
    constexpr ModInt &operator+=(const T rhs) noexcept {
        num = mod(num + rhs);
        return *this;
    }

    template<typename T>
    constexpr ModInt &operator-=(const T rhs) noexcept {
        num = mod(num - rhs);
        return *this;
    }

    template<typename T>
    constexpr ModInt &operator*=(const T rhs) noexcept {
        num = num * mod(rhs) % modulus;
        return *this;
    }

    template<typename T>
    constexpr ModInt &operator/=(const T rhs) noexcept {
        num = num * inv(mod(rhs)) % modulus;
        return *this;
    }

    constexpr bool operator<(const ModInt rhs) noexcept {
        return num < rhs.num;
    }

    constexpr bool operator==(const ModInt rhs) noexcept {
        return num == rhs.num;
    }

    ModInt &operator=(const ModInt rhs) noexcept {
        num = rhs.num;
        return *this;
    }

    template<typename T>
    ModInt &operator=(const T rhs) noexcept {
        num = mod(rhs);
        return *this;
    }
};

template <long long modulus>
std::istream &operator>>(std::istream &lhs, ModInt<modulus> &rhs){
    long long val;
    lhs >> val;
    rhs = val;
    return lhs;
}

template <long long modulus>
std::ostream &operator<<(std::ostream &lhs, ModInt<modulus> rhs){
    lhs << rhs.value();
    return lhs;
}

using mint = ModInt<1000000007LL>;

struct BNF{
    int n;
    string e;
    int pos;
    vector<mint> val;

    BNF(string e_){
        e = e_;
        n = (int)e.size();
        pos = 0;
        val = expression();
    }

    vector<mint> pl(vector<mint> l, vector<mint> r){
        vector<mint> ret(3, 0);

        ret[0] = l[0] * r[0] + l[0] * r[1] + l[1] * r[0];
        ret[1] = l[1] * r[1] + l[1] * r[2] + l[2] * r[1];
        ret[2] = l[2] * r[2] + l[2] * r[0] + l[0] * r[2];

        return ret;
    }

    vector<mint> mi(vector<mint> l, vector<mint> r){
        vector<mint> ret(3, 0);

        ret[0] = l[0] * r[0] + l[0] * r[2] + l[2] * r[0];
        ret[1] = l[1] * r[1] + l[1] * r[0] + l[0] * r[1];
        ret[2] = l[2] * r[2] + l[2] * r[1] + l[1] * r[2];

        return ret;
    }

    vector<mint> ti(vector<mint> l, vector<mint> r){
        vector<mint> ret(3, 0);

        ret[0] = l[0] * r[0] + l[1] * r[2] + l[2] * r[1];
        ret[1] = l[1] * r[1] + l[2] * r[0] + l[0] * r[2];
        ret[2] = l[2] * r[2] + l[0] * r[1] + l[1] * r[0];

        return ret;
    }

    vector<mint> expression(void){
        vector<mint> ret = term();

        while(pos < n){
            if(e[pos] == '+'){
                ++pos;
                ret = pl(ret, term());
                continue;
            }else if(e[pos] == '-'){
                ++pos;
                ret = mi(ret, term());
                continue;
            }

            return ret;
        }

        return ret;
    }

    vector<mint> term(void){
        vector<mint> ret = factor();

        while(pos < n){
            if(e[pos] == '*'){
                ++pos;
                ret = ti(ret, factor());
                continue;
            }

            break;
        }

        return ret;
    }

    vector<mint> factor(void){
        vector<mint> ret(3, 0);

        if(e[pos] == '('){
            ++pos;
            ret = expression();

            if(e[pos] == ')'){
                ++pos;
            }
        }else if(e[pos] == 'R'){
            ret[0] = 1;
            ++pos;
        }else if(e[pos] == 'S'){
            ret[1] = 1;
            ++pos;
        }else if(e[pos] == 'P'){
            ret[2] = 1;
            ++pos;
        }else if(e[pos] == '?'){
            ret[0] = 1;
            ret[1] = 1;
            ret[2] = 1;
            ++pos;
        }

        return ret;
    }
};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);

    int n;
    string e;
    char a;
    cin >> n >> e >> a;

    BNF b(e);

    vector<mint> v = b.val;

    mint ans;
    if(a == 'R'){
        ans = v[0];
    }else if(a == 'S'){
        ans = v[1];
    }else{
        ans = v[2];
    }

    cout << ans << endl;

    cout << flush;

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 34820
final_rank: 2

code_snippet: #include <cmath>
#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <set>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>
#include <random>
#include <sstream>
#include <bitset>
#include <complex>
#include <chrono>
#include <cassert>

using namespace std;

constexpr long long int MOD = 1000'000'007;


enum class Hand {
	Rock, Scissor, Paper
};
int to_int(const Hand hand) {
	switch (hand) {
	case Hand::Rock: return 0;
	case Hand::Scissor: return 1;
	case Hand::Paper: return 2;
	default: throw 0;
	}
}
Hand from_int(const int value) {
	switch (value) {
	case 0: return Hand::Rock;
	case 1: return Hand::Scissor;
	case 2: return Hand::Paper;
	default: throw 0;
	}
}
Hand from_char(const char c) {
	switch (c) {
	case 'R': return Hand::Rock;
	case 'S': return Hand::Scissor;
	case 'P': return Hand::Paper;
	default: throw 0;
	}
}
Hand winner(const Hand left, const Hand right) {
	return (to_int(right) + 3 - to_int(left)) % 3 == 1 ? left : right;
}
Hand loser(const Hand left, const Hand right) {
	return (to_int(right) + 3 - to_int(left)) % 3 == 1 ? right : left;
}
constexpr array<Hand, 3> all_hand{ Hand::Rock, Hand::Scissor, Hand::Paper };

class Token {
public:
	virtual ~Token() = default;
};
class Operator : public Token {
public:
	virtual Hand calc(const Hand left, const Hand right) const = 0;
};
class Plus final : public Operator {
public:
	Hand calc(const Hand left, const Hand right) const override {
		return winner(left, right);
	}
};
class Minus final : public Operator {
public:
	Hand calc(const Hand left, const Hand right) const override {
		return loser(left, right);
	}
};
class Times final : public Operator {
public:
	Hand calc(const Hand left, const Hand right) const override {
		return left == right ? left : from_int(3 - to_int(left) - to_int(right));
	}
};
class Factor : public Token {
public:
	virtual long long int pattern(const Hand hand) const = 0;
};
class Rock : public Factor {
public:
	long long int pattern(const Hand hand) const override {
		return hand == Hand::Rock ? 1 : 0;
	}
};
class Scissors final : public Factor {
public:
	long long int pattern(const Hand hand) const override {
		return hand == Hand::Scissor ? 1 : 0;
	}
};
class Paper final : public Factor {
public:
	long long int pattern(const Hand hand) const override {
		return hand == Hand::Paper ? 1 : 0;
	}
};
class Unknown final : public Factor {
public:
	long long int pattern(const Hand hand) const override {
		return 1;
	}
};
class Expression final : public Factor {
	array<long long int, 3> _pattern;
public:
	Expression(const Factor* left, const Operator* op, const Factor* right){
		_pattern.fill(0);
		for (const auto l : all_hand) {
			for (const auto r : all_hand) {
				_pattern[to_int(op->calc(l, r))] += left->pattern(l) * right->pattern(r) % MOD;
			}
		}
		for (auto& p : _pattern) {
			p %= MOD;
		}
	}
	long long int pattern(const Hand hand) const override {
		return _pattern[to_int(hand)];
	}
};

shared_ptr<Factor> from_token(const vector<shared_ptr<Token>>& token) {
	vector<shared_ptr<Token>> stack;
	for (const auto& t : token) {
		const auto right = dynamic_cast<Factor*>(t.get());
		if (!stack.empty() && right) {
			const auto op = dynamic_pointer_cast<Times>(stack.back());
			if (op) {
				stack.pop_back();
				const auto left = stack.back(); stack.pop_back();
				stack.emplace_back(make_shared<Expression>(dynamic_cast<Factor*>(left.get()), op.get(), right));
			}
			else {
				stack.push_back(t);
			}
		}
		else {
			stack.push_back(t);
		}
	}
	auto left = stack.front();
	for (auto i = 1; i < stack.size(); i += 2) {
		left = make_shared<Expression>(dynamic_cast<Factor*>(left.get()), dynamic_cast<Operator*>(stack[i].get()), dynamic_cast<Factor*>(stack[i + 1].get()));
	}
	return dynamic_pointer_cast<Factor>(left);
}
shared_ptr<Factor> parse_expression(const string& expression) {
	vector<vector<shared_ptr<Token>>> stack(1);
	for (const auto c : expression) {
		switch (c) {
		case 'R': stack.back().push_back(make_shared<Rock>()); break;
		case 'S': stack.back().push_back(make_shared<Scissors>()); break;
		case 'P': stack.back().push_back(make_shared<Paper>()); break;
		case '?': stack.back().push_back(make_shared<Unknown>()); break;
		case '+': stack.back().push_back(make_shared<Plus>()); break;
		case '-': stack.back().push_back(make_shared<Minus>()); break;
		case '*': stack.back().push_back(make_shared<Times>()); break;
		case '(': stack.emplace_back(); break;
		case ')': {
			const auto last = from_token(stack.back());
			stack.pop_back();
			stack.back().push_back(last);
		}
				break;
		default: throw 0;
		}
	}
	assert(stack.size() == 1);
	return from_token(stack.front());
}
int main() {
	int n; cin >> n;
	string e; cin >> e;
	char a; cin >> a;
	const auto target = from_char(a);
	const auto expression = parse_expression(e);
	cout << expression->pattern(target) << '\n';
}
accuracy: 1
time_ms: 30
memory_kb: 20728
final_rank: 4

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005

enum Type{
	R,
	S,
	P,
};


struct Info{

	ll num[3];
};


char line[SIZE];
Info calc_E(int left,int right,int DEPTH);
Info calc_T(int left,int right,int DEPTH);
Info calc_F(int left,int right,int DEPTH);
Info calc_NUM(int left,int right,int DEPTH);

int CLOSE_POS[SIZE];

vector<int> PLUS_MINUS[SIZE/2];
vector<int> MULT[SIZE/2];


Info calc_E(int left,int right,int DEPTH){

	queue<int> Q;

	if(PLUS_MINUS[DEPTH].size() > 0){

		int L = lower_bound(PLUS_MINUS[DEPTH].begin(),PLUS_MINUS[DEPTH].end(),left)-PLUS_MINUS[DEPTH].begin();
		int R = upper_bound(PLUS_MINUS[DEPTH].begin(),PLUS_MINUS[DEPTH].end(),right)-PLUS_MINUS[DEPTH].begin();
		R--;

		if(L <= R){

			for(int i = L; i <= R; i++){

				Q.push(PLUS_MINUS[DEPTH][i]);
			}
		}
	}



	if(Q.empty()){ //深さDEPTHの+-がない
		return calc_T(left,right,DEPTH);
	}

	Info tmp = calc_E(left,Q.front()-1,DEPTH),tmp_right;


	/*for(int i = 0; i < 3; i++){

		printf("tmp.num[%d]:%lld\n",i,tmp.num[i]);
	}*/

	while(!Q.empty()){
		int loc = Q.front();
		Q.pop();

		if(Q.empty()){
			tmp_right = calc_T(loc+1,right,DEPTH);
		}else{
			tmp_right = calc_T(loc+1,Q.front()-1,DEPTH);
		}

		/*for(int i = 0; i < 3; i++){

			printf("tmp_right.num[%d]:%lld\n",i,tmp_right.num[i]);
		}*/

		Info next_tmp;


		if(line[loc] == '+'){

			next_tmp.num[R] = (tmp.num[R]*(tmp_right.num[R]+tmp_right.num[S])+tmp.num[S]*tmp_right.num[R])%MOD;
			next_tmp.num[S] = (tmp.num[S]*(tmp_right.num[S]+tmp_right.num[P])+tmp.num[P]*tmp_right.num[S])%MOD;
			next_tmp.num[P] = (tmp.num[P]*(tmp_right.num[R]+tmp_right.num[P])+tmp.num[R]*tmp_right.num[P])%MOD;

		}else{ //'-'

			next_tmp.num[R] = (tmp.num[R]*(tmp_right.num[R]+tmp_right.num[P])+tmp.num[P]*tmp_right.num[R])%MOD;
			next_tmp.num[S] = (tmp.num[S]*(tmp_right.num[R]+tmp_right.num[S])+tmp.num[R]*tmp_right.num[S])%MOD;
			next_tmp.num[P] = (tmp.num[P]*(tmp_right.num[S]+tmp_right.num[P])+tmp.num[S]*tmp_right.num[P])%MOD;
		}

		tmp = next_tmp;
	}

	return tmp;
}

Info calc_T(int left,int right,int DEPTH){

	queue<int> Q;

	//深さDEPTHの、*,/を探す
	if(MULT[DEPTH].size() > 0){

		int L = lower_bound(MULT[DEPTH].begin(),MULT[DEPTH].end(),left)-MULT[DEPTH].begin();
		int R = upper_bound(MULT[DEPTH].begin(),MULT[DEPTH].end(),right)-MULT[DEPTH].begin();
		R--;

		if(L <= R){

			for(int i = L; i <= R; i++){

				Q.push(MULT[DEPTH][i]);
			}

		}
	}

	if(Q.empty()){ //深さDEPTHの*がない
		return calc_F(left,right,DEPTH);
	}

	Info tmp = calc_T(left,Q.front()-1,DEPTH),tmp_right;

	while(!Q.empty()){
		int loc = Q.front();
		Q.pop();

		if(Q.empty()){
			tmp_right = calc_F(loc+1,right,DEPTH);
		}else{
			tmp_right = calc_F(loc+1,Q.front()-1,DEPTH);
		}

		Info next_tmp;

		if(line[loc] == '*'){

			next_tmp.num[R] = (tmp.num[R]*tmp_right.num[R]+tmp.num[S]*tmp_right.num[P]+tmp.num[P]*tmp_right.num[S])%MOD;
			next_tmp.num[S] = (tmp.num[R]*tmp_right.num[P]+tmp.num[S]*tmp_right.num[S]+tmp.num[P]*tmp_right.num[R])%MOD;
			next_tmp.num[P] = (tmp.num[R]*tmp_right.num[S]+tmp.num[S]*tmp_right.num[R]+tmp.num[P]*tmp_right.num[P])%MOD;
		}
		tmp = next_tmp;
	}
	return tmp;
}

Info calc_F(int left,int right,int DEPTH){

	if(line[left] != '('){

		return calc_NUM(left,right,DEPTH);

	}else{ // line[left] == '('

		int close_pos = CLOSE_POS[left];

		return calc_E(left+1,close_pos-1,DEPTH+1);
	}
}

Info calc_NUM(int left,int right,int DEPTH){

	Info ret;
	for(int i = 0; i < 3; i++){

		ret.num[i] = 0;
	}

	switch(line[left]){
	case 'R':
		ret.num[R]++;
		break;
	case 'S':
		ret.num[S]++;
		break;
	case 'P':
		ret.num[P]++;
		break;
	case '?':
		ret.num[R]++;
		ret.num[S]++;
		ret.num[P]++;
		break;
	}


	return ret;
}


int main(){

	int LEN;

	scanf("%d",&LEN);
	scanf("%s",line);

	char A[2];
	scanf("%s",A);

	int depth = 0;

	//深さと演算子を前計算
	for(int i = 0; i < LEN; ){
		if(line[i] == '(')depth++;
		else if(line[i] == ')')depth--;

		if(line[i] == '+' || line[i] == '-'){

			PLUS_MINUS[depth].push_back(i);

		}else if(line[i] == '*'){

			MULT[depth].push_back(i);
		}

		i++;
	}

	//開きかっこに対する閉じかっこを前計算
	stack<int> ST;
	for(int i = 0; i < LEN; i++){
		if(line[i] == '('){

			ST.push(i);
		}else if(line[i] == ')'){

			CLOSE_POS[ST.top()] = i;
			ST.pop();
		}
	}


	Info ret = calc_E(0,LEN-1,0);

	switch(A[0]){

	case 'R':
		printf("%lld\n",ret.num[R]);
		break;

	case 'S':
		printf("%lld\n",ret.num[S]);
		break;

	case 'P':
		printf("%lld\n",ret.num[P]);
		break;

	}

	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 181968
final_rank: 5