Problem:
グリコ on Line
問題
高橋君と青木君は数直線上でゲームをしています。
ゲームは $N$ ターン行います。各ターンでは二人でじゃんけんを行い、それぞれ以下のように行動します。
「現在位置を座標 $x$ としたとき、座標 $x + 1$ または 座標 $x - 1$ に移動する」という操作を考えます。
じゃんけんにグーで勝った場合は、勝った人がこの操作を必ず合計 $3$ 回行います。負けた人は何もしません。
じゃんけんにチョキで勝った場合は、勝った人がこの操作を必ず合計 $6$ 回行います。負けた人は何もしません。
じゃんけんにパーで勝った場合は、勝った人がこの操作を必ず合計 $6$ 回行います。負けた人は何もしません。
あいこの場合はお互い何もしません。
初め高橋君は原点にいて、 $N$ ターン後には座標 $X$ にいました。
青木君が出した手が
R
,
S
,
P
からなる長さ $N$ の文字列 $S$ として与えられるとき、高橋君が出した手としてあり得るものは何通りあるか求めてください。
ただし、
R
はグー、
S
はチョキ、
P
はパーを表します。
また、答えが非常に大きくなる可能性があるので $10^9+7$ で割った余りを出力してください。
制約
$1 \leq N \leq 500000$
$-500000 \leq X \leq 500000$
$S$ は
R
,
S
,
P
からなる長さ $N$ の文字列
入力
$N$ $X$
$S$
出力
高橋君が出した手としてあり得るものは何通りあるか求めてください。答えが非常に大きくなる可能性があるので $10^9+7$ で割った余りを出力してください。
入力例 1
3 1
RSP
出力例 1
9
例えば高橋くんの出した手が
RRR
の場合、 $1$ ターン目と $3$ ターン目はじゃんけんに勝っていないので移動できません。 $2$ ターン目はグーで勝っているので $3$ 回移動することができます。このとき $+1, -1, +1$ のように移動することで最終的に座標 $1$ まで移動することができます。同様に高橋くんが
SRP
や
PRP
を出した場合にも座標 $1$ に移動することができます。
入力例 2
5 5
RPRPR
出力例 2
0
どんな手を出しても座標 $5$ に移動することは出来ません。
入力例 3
22 -60
SRSSPRPRPPPRPPPRPPPPPR
出力例 3
621423603
答えが非常に大きくなる可能性があるので $10^9+7$ で割った余りを出力してください。

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=2167167167167167167;
const int INF=2100000000;
const ll mod=1e9+7;
#define rep(i,a) for (ll i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}
template<class T> T min(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmin(ans,x);return ans;}
template<class T> T max(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmax(ans,x);return ans;}
template<class T> T sum(vector<T> &a){assert(!a.empty());T ans=a[0]-a[0];for(auto &x:a) ans+=x;return ans;}

namespace po167{
struct combination{
	int upper;
	long long MOD;
	std::vector<long long> fact;
	std::vector<long long> rev;
	std::vector<long long> fact_rev;
	combination(int max,long long mod):upper(max),MOD(mod),fact(max+1),rev(max+1),fact_rev(max+1){
		for(long long i=0;i<=max;i++){
			if(i<2){
				fact[i]=1;
				fact_rev[i]=1;
				rev[i]=1;
				continue;
			}
			fact[i]=(fact[i-1]*i)%mod;
			rev[i]=mod-((mod/i)*rev[mod%i])%mod;
			fact_rev[i]=(fact_rev[i-1]*rev[i])%mod;
		}
	}
	long long Comb(int x,int y){
		assert(upper>=x);
		if (x<y||y<0||x<0) return 0;
		return (((fact_rev[y]*fact_rev[x-y])%MOD)*fact[x])%MOD;
	}
	long long P(int x,int y){
		assert(upper>=x);
		if (x<y||y<0||x<0) return 0;
		return (fact_rev[x-y]*fact[x])%MOD;
	}
};
}
using po167::combination;



void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t=1;
	//cin>>t;
	rep(i,t) solve();
	//while(1) solve();
}

void solve(){
	ll N,X;
	cin>>N>>X;
	X=abs(X);
	string S;
	cin>>S;
	ll A=0;
	for(auto c:S) A+=(c=='S');
	combination table(N,mod);
	vector<ll> p(N-A+2);
	ll tmp=1;
	for(int i=N-A;i>=0;i--){
		p[i]=(p[i+1]+tmp*table.Comb(N-A,i))%mod;
		tmp=(tmp*2ll)%mod;
	}
	//vec_out(p);
	tmp=1;
	ll ans=0;
	for(int i=A;i>=0;i--){
		ll D=(max(0ll,X-3*i)+5)/6;
		chmin(D,N-A+1);
		if(((i^X)&1)==0){
			ans+=(((p[D]*tmp)%mod)*table.Comb(A,i))%mod;
			ans%=mod;
		}
		tmp=(tmp*2ll)%mod;
	}
	cout<<ans<<"\n";
}
accuracy: 1
time_ms: 10
memory_kb: 19224
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long int lli;
const lli mod = 1e9 +7;

lli ExGCD(lli a, lli b, lli &x, lli &y){
    lli d=a;
    x=1; y=0;
    if(b!=0){ d=ExGCD(b, a%b, y, x); y-=a/b*x; }
    return d;
}
lli inverse(lli a, lli mod){
    lli x,y;
    ExGCD(a, mod, x, y);
    return x>0? x: mod+x;
}
lli inverse(lli a){
    return inverse(a, mod);
}

constexpr int arrmax=500001;
lli fact[arrmax];
lli inv[arrmax];
void maketable(){
    fact[0] = 1;
    for(int i=0; i<arrmax-1; i++){
        fact[i+1] = fact[i]*(i+1) %mod;
    }
    inv[arrmax-1] = inverse(fact[arrmax-1]);
    for(int i=arrmax-1; i>0; i--){
        inv[i-1] = inv[i]*i %mod;
    }
}
lli permutation(lli n, lli r){
    if(r<0 or n<r) return 0;
    return fact[n] *inv[n-r] %mod;
}
lli combination(lli n, lli r){
    if(r<0 or n<r) return 0;
    return fact[n] *inv[n-r] %mod *inv[r] %mod;
}

lli modpow(lli a, lli p, lli mod){
    lli ret = 1;
    for(int i=63; i>=0; i--){
        ret *= ret;
        ret %= mod;
        if((1LL<<i & p) != 0){
            ret *= a;
            ret %= mod;
        }
    }
    return ret;
}
lli modpow(lli a, lli p){
    return modpow(a, p, mod);
}

int main(){
    int n,x;
    string s;
    cin >> n >> x >> s;
    x = abs(x);

    int num_s = 0;
    for(char c: s){
        if(c == 'S') num_s++;
    }

    maketable();
    vector<lli> csum(n+1, 0);
    for(int i=0; i<=n-num_s; i++){
        csum[i] = combination(n-num_s, i) *modpow(2, n-num_s -i) %mod;
    }
    for(int i=n-1; i>=0; i--){
        csum[i] += csum[i+1];
        csum[i] %= mod;
    }

    lli ans = 0;
    for(int i=(x%2==0)? 0: 1; i<=num_s; i+=2){
        int nx = max(x -3*i, 0);
        int rem = (nx +6-1) /6;
        if(rem > n) continue;
        ans += combination(num_s, i) *modpow(2, num_s -i) %mod *csum[rem] %mod;
    }
    ans %= mod;
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 15452
final_rank: 9

code_snippet: #include <bits/stdc++.h>

using namespace std;

// {{{ ModInt
template<int _MOD>
struct ModInt {
    static const auto MOD = _MOD;
    template<class T> using integral_only = typename enable_if<is_integral<T>::value>::type;

    int x;
    constexpr ModInt() : x() {}

    template<class T, integral_only<T>* = nullptr>
    ModInt(T _x=0) {
        x = _x % MOD;
        if(x<0) x+=MOD;
    }
    ModInt operator-() const { return {x == 0? 0 : MOD-x}; }
    ModInt& operator+=(const ModInt a) {
        if ((x += a.x) >= MOD) x -= MOD;
        return *this;
    }
    ModInt& operator-=(const ModInt a) {
        if ((x += MOD-a.x) >= MOD) x -= MOD;
        return *this;
    }
    ModInt& operator*=(const ModInt a) {
        x = (long long)x * a.x % MOD;
        return *this;
    }
    ModInt& operator/=(const ModInt a) {
        return (*this) *= a.inv();
    }

    ModInt operator+(const ModInt a) const { return ModInt(*this) += a; }
    ModInt operator-(const ModInt a) const { return ModInt(*this) -= a; }
    ModInt operator*(const ModInt a) const { return ModInt(*this) *= a; }
    ModInt operator/(const ModInt a) const { return ModInt(*this) /= a; }
    ModInt inv() const {
        // for prime MOD
        return pow(MOD-2);
    }
    ModInt inv2() const {
        // work for non-prime MOD if gcd(x,MOD) = 1
        int a = x, b = MOD, u = 1, v = 0;
        while(b != 0) {
            int t = a / b;
            a -= t * b;
            u -= t * v;
            swap(a, b);
            swap(u, v);
        }
        return u;
    }
    template<class T, integral_only<T>* = nullptr>
    ModInt pow(T t) const {
        ModInt r = 1, p = *this;
        while(t) {
            if(t & 1) r *= p;
            p *= p;
            t >>= 1;
        }
        return r;
    }

    bool operator==(ModInt rhs) const { return x == rhs.x; }
    bool operator!=(ModInt rhs) const { return x != rhs.x; }
    bool operator<(ModInt rhs) const { return x < rhs.x; }
    bool operator<=(ModInt rhs) const { return x <= rhs.x; }
    bool operator>(ModInt rhs) const { return x > rhs.x; }
    bool operator>=(ModInt rhs) const { return x >= rhs.x; }

    friend string to_string(ModInt i) { return to_string(i.x); }
    friend istream& operator>>(istream&i,ModInt&a) { return i>>a.x; }
    friend ostream& operator<<(ostream&o,const ModInt&a) { return o<<a.x; }
};
// }}}
const int MOD=1000000007;
using mint=ModInt<MOD>;

const int N=500010;
mint fact[N],ifact[N];
mint C( int n, int r ) {
    if ( r>n || r<0 ) return 0;
    return fact[n]*ifact[r]*ifact[n-r];
}
void init_comb() {
    fact[0]=1;
    for ( int i=1; i<N; i++ ) fact[i]=fact[i-1]*i;
    ifact[N-1]=fact[N-1].inv();
    for ( int i=N-1; i>0; i-- ) ifact[i-1]=ifact[i]*i;
}
int main() {
    init_comb();
    int n,x;
    cin>>n>>x;
    x=abs(x);
    string s;
    cin>>s;
    int S=0,R=0,P=0;
    for ( int i=0; i<n; i++ ) {
        if ( s[i]=='R' ) P++;
        if ( s[i]=='S' ) R++;
        if ( s[i]=='P' ) S++;
    }
    vector<mint> p2(n+1);
    p2[0]=1;
    for ( int i=0; i<n; i++ ) {
        p2[i+1]=p2[i]*2;
    }
    vector<mint> pref(n+5);
    for ( int i=0; i<=n-R; i++ ) {
        pref[i+1]=pref[i]+C(n-R,i)*p2[n-R-i];
    }
    mint ans=0;
    if ( x%2 ) {
        for ( int i=1; i<=R; i+=2 ) {
            int j=(max(0,x-i*3)+5)/6;
            if ( j>P+S ) continue;
            ans+=C(R,i)*p2[R-i]*(pref[n-R+1]-pref[j]);
        }
    } else {
        for ( int i=0; i<=R; i+=2 ) {
            int j=(max(0,x-i*3)+5)/6;
            if ( j>P+S ) continue;
            ans+=C(R,i)*p2[R-i]*(pref[n-R+1]-pref[j]);
        }
    }
    cout<<ans<<'\n';
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 11436
final_rank: 1

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

using namespace std;

typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;


#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()

#define MOD 1000000007

template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-6, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

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

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt< 1000000007 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;

  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }

  inline T fact(int k) const { return _fact[k]; }

  inline T rfact(int k) const { return _rfact[k]; }

  inline T inv(int k) const { return _inv[k]; }

  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }

  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }

  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};

int modpow(ll x, ll n, int mod) {
  if(x == 0) return 0;
  
  ll res = 1;
  while(n) {
    if(n&1) res = res*x % mod;
    x = x*x%mod;
    n >>= 1;
  }
  return res;
}

modint cum[501010];
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(7);
  
  int N, X; cin >> N >> X;
  string S; cin >> S;
  Combination<modint> comb(501010);
  X = abs(X);
  int p=0,r=0,s=0;
  REP(i,N) {
    if(S[i] == 'R') r++;
    else if(S[i] == 'S') s++;
    else p++;
  }

  for(int i=0; i<=p+r; i++) {
    cum[i+1] += cum[i];
    cum[i+1] += modint(2).pow(p+r-i) * comb.C(p+r, i);
  }
  modint ans = 0;
  for(int i=0; i<=s; i++) {
    //i回(グーで)勝ったとき i*3の移動
    //s-i回(パーかチョキ)
    if(i%2 == 1 && X%2 == 0) continue;
    if(i%2 == 0 && X%2 == 1) continue;
    
    modint t = modint(2).pow(s-i) * comb.C(s, i);
    
    if(3*i+6*(p+r) < X) continue;

    int mins = 1e9;
    if(-3*i <= X && X <= 3*i) {
      mins = 0;
    }else{
      mins = (X-3*i + 5)/6;
    }
    t *= (cum[p+r+1] - cum[mins]);
    ans += t;
  }
  cout << ans << endl;
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 11220
final_rank: 4

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 <cfloat>

using namespace std;

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

long long int power(const long long int base, const int exp) {
	if (exp == 0) return 1LL;
	if (exp == 1) return base % MOD;
	return power(base * base % MOD, exp >> 1) * power(base, exp & 1) % MOD;
}
int main() {
	int n, x; cin >> n >> x;
	string hand; cin >> hand;
	vector<int> count(3, 0);
	for (const auto h : hand) {
		switch (h) {
		case 'R': ++count[0]; break;
		case 'S': ++count[1]; break;
		case 'P': ++count[2]; break;
		default: throw 0;
		}
	}
	vector<long long int> fact(n + 1, 1), div(n + 1, 1), inv(n + 1, 1);
	for (auto i = 2; i < fact.size(); ++i) {
		fact[i] = i * fact[i - 1] % MOD;
		div[i] = (MOD - MOD / i) * div[MOD % i] % MOD;
		inv[i] = div[i] * inv[i - 1] % MOD;
	}
	const auto combination = [&](const int n, const int r) {return fact[n] * inv[r] % MOD * inv[n - r] % MOD; };
	vector<long long int> combination_sum(n - count[1] + 1, 0);
	for (auto i = 1; i < combination_sum.size(); ++i) {
		combination_sum[i] = (combination(n - count[1], i - 1) * power(2, n - count[1] - i + 1) % MOD + combination_sum[i - 1]) % MOD;
	}
	const auto pow = power(3, n - count[1]);
	long long int sum_pattern{ 0 };
	for (auto i = (x & 1); i <= count[1]; i += 2) {
		auto rest = max(abs(x) - 3 * i, 0);
		if (rest > (n - count[1]) * 6) continue;
		const auto rock_pattern = combination(count[1], i) * power(2, count[1] - i) % MOD;
		const auto rest_pattern = (pow - combination_sum[(rest + 5) / 6] + MOD) % MOD;
		sum_pattern = (sum_pattern + rock_pattern * rest_pattern % MOD) % MOD;
	}
	cout << sum_pattern << '\n';
}
accuracy: 1
time_ms: 60
memory_kb: 19428
final_rank: 6

code_snippet: #define rep(i,n) for (int i=0;i < (int)(n);i++)
#define ALL(v) v.begin(),v.end()
typedef long long ll;

#include <bits/stdc++.h>
using namespace std;

const int MAX=1010000;
const int MOD=1e9+7;

ll modpow(ll x,ll n){
  ll ans=1;
  while(n){
    if(n&1) ans=ans*x%MOD;
    x=x*x%MOD;
    n/=2;
  }
  return ans;
}

ll fac[MAX], finv[MAX], inv[MAX];
void init(){
  fac[0]=fac[1]=1;
  finv[0]=finv[1]=1;
  inv[1]=1;
  for(int i=2;i<MAX;i++){
    fac[i]=fac[i-1]*i%MOD;
    inv[i]=MOD-inv[MOD%i]*(MOD/i)%MOD;
    finv[i]=finv[i-1]*inv[i]%MOD;
  }
}

ll nCr(int n,int k){
  if(n<k) return 0;
  if(n<0 || k<0) return 0;
  return fac[n]*(finv[k]*finv[n-k]%MOD)%MOD;
}

ll A[500050];

int main(){
  ll n,x;
  string s;
  cin>>n>>x>>s;
  
  ll cnts=0;
  rep(i,n){
    if(s[i]=='S') cnts++;
  }
  ll cntpr=n-cnts;
  
  init();
  
  rep(i,500001) A[i]=nCr(cntpr,i)*modpow(2,cntpr-i)%MOD;
  rep(i,500000) A[i+1]=(A[i+1]+A[i])%MOD;
  
  x=max(x,-x);
  ll ans=0,z;
  for(int i=x%2;i<=cnts;i+=2){
    if(x-3*i<0) z=0; 
    else z=(x-3*i+5)/6;
    if(z>cntpr) continue;
    if(z==0) ans=(ans+nCr(cnts,i)*modpow(2,cnts-i)%MOD*A[cntpr]%MOD)%MOD;
    else ans=(ans+nCr(cnts,i)*modpow(2,cnts-i)%MOD*(A[cntpr]-A[z-1])%MOD)%MOD;
  }
  cout<<(ans+MOD)%MOD<<endl;
  
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 31316
final_rank: 8

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 1000005

ll N,X;
ll table[SIZE];
char buf[SIZE];


ll POW[SIZE];
ll fact[SIZE],inv_fact[SIZE];

ll mod_pow(ll x,ll count, ll mod){

	if(count == 0)return 1;
	ll ret = mod_pow((x*x)%mod,count/2,mod);
	if(count%2 == 1){

		ret = (ret*x)%mod;
	}
	return ret;
}

ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}

ll nCk(ll n,ll k){

	if(k > n)return 0;

	ll ret = fact[n]*inv_fact[k];
	ret %= MOD;
	ret *= inv_fact[n-k];

	return ret%MOD;
}

ll nPk(ll n,ll k){

	if(k > n)return 0;

	ll ret = fact[n]*inv_fact[n-k];

	return ret%MOD;
}


int main(){

	POW[0] = 1;
	for(int i = 1; i < SIZE; i++){

		POW[i] = POW[i-1]*2;
		POW[i] %= MOD;
	}

	fact[0] = 1;
	for(ll i = 1; i < SIZE; i++){
		fact[i] = i*fact[i-1];
		fact[i] %= MOD;
	}
	inv_fact[SIZE-1] = mod_inverse(fact[SIZE-1],MOD);
	for(ll i = SIZE-1; i >= 1; i--){

		inv_fact[i-1] = inv_fact[i]*i;
		inv_fact[i-1] %= MOD;
	}


	scanf("%lld %lld",&N,&X);

	X = abs(X);

	scanf("%s",buf);

	ll num_gu = 0,num_other = 0;

	for(int i = 0; buf[i] != '\0'; i++){

		if(buf[i] == 'S'){

			num_gu++;
		}else{

			num_other++;
		}
	}

	for(ll i = 0; i <= num_other; i++){ //その他で勝つ個数

		table[i] = nCk(num_other,i)*POW[num_other-i]%MOD;
		if(i > 0){

			table[i] += table[i-1];
			table[i] %= MOD;
		}
	}


	ll ans = 0;
	ll left,right,mid;

	for(ll a = 0; a <= num_gu; a++){
		if((a%2) != (X%2))continue;

		ll base = POW[num_gu-a]*nCk(num_gu,a); //グーを使う個数
		base %= MOD;

		ll tmp = a/2; //そのほかを使う個数

		//最大絶対値
		ll maxi = 6*tmp;

		if(a%2 == 1){

			maxi += 3;
		}

		//その他で勝つ個数
		left = 0,right = num_other,mid = (left+right)/2;
		ll mini = -1;

		while(left <= right){

			if(maxi+6*mid >= X){

				mini = mid;
				right = mid-1;
			}else{

				left = mid+1;
			}
			mid = (left+right)/2;
		}

		if(mini == -1)continue;

		ll mult;

		//mini個以上なら作れる
		if(mini == 0){

			mult = table[num_other];

		}else{

			mult = (table[num_other]-table[mini-1]+MOD)%MOD;
		}

		base *= mult;
		base %= MOD;

		ans += base;
		ans %= MOD;
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 31012
final_rank: 5

code_snippet: #line 2 "/home/yuruhiya/programming/library/template/template_no_Ruby.cpp"
#include <bits/stdc++.h>
#line 4 "/home/yuruhiya/programming/library/template/constants.cpp"
#include <string_view>
#line 7 "/home/yuruhiya/programming/library/template/constants.cpp"

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define rrep(i, n) for (int i = (n)-1; i >= 0; --i)
#define rfor(i, m, n) for (int i = (m); i >= (n); --i)
#define unless(c) if (!(c))
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define range_it(a, l, r) (a).begin() + (l), (a).begin() + (r)

using namespace std;
using ll = long long;
using LD = long double;
using VB = vector<bool>;
using VVB = vector<VB>;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using VS = vector<string>;
using VD = vector<LD>;
using PII = pair<int, int>;
using VP = vector<PII>;
using PLL = pair<ll, ll>;
using VPL = vector<PLL>;
template <class T> using PQ = priority_queue<T>;
template <class T> using PQS = priority_queue<T, vector<T>, greater<T>>;
constexpr int inf = 1000000000;
constexpr long long inf_ll = 1000000000000000000ll, MOD = 1000000007;
constexpr long double PI = 3.14159265358979323846, EPS = 1e-12;
namespace CharacterClass {
	constexpr string_view
	    digit = "0123456789",
	    xdigit = "0123456789ABCDEFabcdef", lower = "abcdefghijklmnopqrstuvwxyz",
	    upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
	    alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
	    alnum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
	    word = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz",
	    punct = R"(!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)",
	    graph =
	        R"(!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~)",
	    print =
	        R"( !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~)",
	    blank = " \t", space = " \t\n\r\f\v";
}  // namespace CharacterClass
#line 7 "/home/yuruhiya/programming/library/template/Input.cpp"
using namespace std;

#ifdef _WIN32
#define getchar_unlocked _getchar_nolock
#define putchar_unlocked _putchar_nolock
#define fwrite_unlocked fwrite
#define fflush_unlocked fflush
#endif
class Scanner {
	static int gc() {
		return getchar_unlocked();
	}
	static char next_char() {
		char c;
		read(c);
		return c;
	}
	template <class T> static void read(T& v) {
		cin >> v;
	}
	static void read(char& v) {
		while (isspace(v = gc()))
			;
	}
	static void read(bool& v) {
		v = next_char() != '0';
	}
	static void read(string& v) {
		v.clear();
		for (char c = next_char(); !isspace(c); c = gc()) v += c;
	}
	static void read(int& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(long long& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(double& v) {
		v = 0;
		double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	static void read(long double& v) {
		v = 0;
		long double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	template <class T, class U> static void read(pair<T, U>& v) {
		read(v.first);
		read(v.second);
	}
	template <class T> static void read(vector<T>& v) {
		for (auto& e : v) read(e);
	}
	template <size_t N = 0, class T> static void read_tuple_impl(T& v) {
		if constexpr (N < tuple_size_v<T>) {
			read(get<N>(v));
			read_tuple_impl<N + 1>(v);
		}
	}
	template <class... T> static void read(tuple<T...>& v) {
		read_tuple_impl(v);
	}
	struct ReadVectorHelper {
		size_t n;
		ReadVectorHelper(size_t _n) : n(_n) {}
		template <class T> operator vector<T>() {
			vector<T> v(n);
			read(v);
			return v;
		}
	};
	struct Read2DVectorHelper {
		size_t n, m;
		Read2DVectorHelper(const pair<size_t, size_t>& nm) : n(nm.first), m(nm.second) {}
		template <class T> operator vector<vector<T>>() {
			vector<vector<T>> v(n, vector<T>(m));
			read(v);
			return v;
		}
	};

public:
	string read_line() const {
		string v;
		for (char c = gc(); c != '\n' && c != '\0'; c = gc()) v += c;
		return v;
	}
	template <class T> T read() const {
		T v;
		read(v);
		return v;
	}
	template <class T> vector<T> read_vector(size_t n) const {
		vector<T> a(n);
		read(a);
		return a;
	}
	template <class T> operator T() const {
		return read<T>();
	}
	int operator--(int) const {
		return read<int>() - 1;
	}
	ReadVectorHelper operator[](size_t n) const {
		return ReadVectorHelper(n);
	}
	Read2DVectorHelper operator[](const pair<size_t, size_t>& nm) const {
		return Read2DVectorHelper(nm);
	}
	void operator()() const {}
	template <class H, class... T> void operator()(H&& h, T&&... t) const {
		read(h);
		operator()(forward<T>(t)...);
	}

private:
	template <template <class...> class, class...> struct Multiple;
	template <template <class...> class V, class Head, class... Tail>
	struct Multiple<V, Head, Tail...> {
		template <class... Args> using vec = V<vector<Head>, Args...>;
		using type = typename Multiple<vec, Tail...>::type;
	};
	template <template <class...> class V> struct Multiple<V> { using type = V<>; };
	template <class... T> using multiple_t = typename Multiple<tuple, T...>::type;
	template <size_t N = 0, class T> void multiple_impl(T& t) const {
		if constexpr (N < tuple_size_v<T>) {
			auto& vec = get<N>(t);
			using V = typename remove_reference_t<decltype(vec)>::value_type;
			vec.push_back(read<V>());
			multiple_impl<N + 1>(t);
		}
	}

public:
	template <class... T> auto multiple(size_t h) const {
		multiple_t<T...> result;
		while (h--) multiple_impl(result);
		return result;
	}
} in;
#define inputs(T, ...) \
	T __VA_ARGS__;     \
	in(__VA_ARGS__)
#define ini(...) inputs(int, __VA_ARGS__)
#define inl(...) inputs(long long, __VA_ARGS__)
#define ins(...) inputs(string, __VA_ARGS__)
#line 7 "/home/yuruhiya/programming/library/template/Output.cpp"
#include <charconv>
#line 10 "/home/yuruhiya/programming/library/template/Output.cpp"
using namespace std;

struct BoolStr {
	const char *t, *f;
	BoolStr(const char* _t, const char* _f) : t(_t), f(_f) {}
} Yes("Yes", "No"), yes("yes", "no"), YES("YES", "NO"), Int("1", "0");
struct DivStr {
	const char *d, *l;
	DivStr(const char* _d, const char* _l) : d(_d), l(_l) {}
} spc(" ", "\n"), no_spc("", "\n"), end_line("\n", "\n"), comma(",", "\n"),
    no_endl(" ", "");
class Printer {
	BoolStr B{Yes};
	DivStr D{spc};

public:
	void print(int v) const {
		char buf[12]{};
		if (auto [ptr, e] = to_chars(begin(buf), end(buf), v); e == errc{}) {
			fwrite(buf, sizeof(char), ptr - buf, stdout);
		} else {
			assert(false);
		}
	}
	void print(long long v) const {
		char buf[21]{};
		if (auto [ptr, e] = to_chars(begin(buf), end(buf), v); e == errc{}) {
			fwrite(buf, sizeof(char), ptr - buf, stdout);
		} else {
			assert(false);
		}
	}
	void print(bool v) const {
		print(v ? B.t : B.f);
	}
	void print(vector<bool>::reference v) const {
		print(v ? B.t : B.f);
	}
	void print(char v) const {
		putchar_unlocked(v);
	}
	void print(const char* v) const {
		fwrite_unlocked(v, 1, strlen(v), stdout);
	}
	void print(double v) const {
		printf("%.20f", v);
	}
	void print(long double v) const {
		printf("%.20Lf", v);
	}
	template <class T> void print(const T& v) const {
		cout << v;
	}
	template <class T, class U> void print(const pair<T, U>& v) const {
		print(v.first);
		print(D.d);
		print(v.second);
	}
	template <class InputIterater>
	void print_range(const InputIterater& begin, const InputIterater& end) const {
		for (InputIterater i = begin; i != end; ++i) {
			if (i != begin) print(D.d);
			print(*i);
		}
	}
	template <class T> void print(const vector<T>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T, size_t N> void print(const array<T, N>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T> void print(const vector<vector<T>>& v) const {
		for (size_t i = 0; i < v.size(); ++i) {
			if (i) print(D.l);
			print(v[i]);
		}
	}

	Printer() = default;
	Printer(const BoolStr& _boolstr, const DivStr& _divstr) : B(_boolstr), D(_divstr) {}
	Printer& operator()() {
		print(D.l);
		return *this;
	}
	template <class H> Printer& operator()(H&& h) {
		print(h);
		print(D.l);
		return *this;
	}
	template <class H, class... T> Printer& operator()(H&& h, T&&... t) {
		print(h);
		print(D.d);
		return operator()(forward<T>(t)...);
	}
	template <class InputIterator>
	Printer& range(const InputIterator& begin, const InputIterator& end) {
		print_range(begin, end);
		print(D.l);
		return *this;
	}
	template <class T> Printer& range(const T& a) {
		range(a.begin(), a.end());
		return *this;
	}
	template <class... T> void exit(T&&... t) {
		operator()(forward<T>(t)...);
		std::exit(EXIT_SUCCESS);
	}
	Printer& flush() {
		fflush_unlocked(stdout);
		return *this;
	}
	Printer& set(const BoolStr& b) {
		B = b;
		return *this;
	}
	Printer& set(const DivStr& d) {
		D = d;
		return *this;
	}
	Printer& set(const char* t, const char* f) {
		B = BoolStr(t, f);
		return *this;
	}
} out;
#line 7 "/home/yuruhiya/programming/library/template/functions.cpp"
using namespace std;

template <class T = long long> constexpr T TEN(size_t n) {
	T result = 1;
	for (size_t i = 0; i < n; ++i) result *= 10;
	return result;
}
template <class T, class U,
          enable_if_t<is_integral_v<T> && is_integral_v<U>, nullptr_t> = nullptr>
constexpr auto div_ceil(T n, U m) {
	return (n + m - 1) / m;
}
template <class T, class U> constexpr auto div_ceil2(T n, U m) {
	return div_ceil(n, m) * m;
}
template <class T> constexpr T triangle(T n) {
	return (n & 1) ? (n + 1) / 2 * n : n / 2 * (n + 1);
}
template <class T> constexpr T nC2(T n) {
	return (n & 1) ? (n - 1) / 2 * n : n / 2 * (n - 1);
}
template <class T, class U> constexpr auto middle(const T& l, const U& r) {
	return l + (r - l) / 2;
}
template <class T, class U, class V>
constexpr bool in_range(const T& v, const U& lower, const V& upper) {
	return lower <= v && v < upper;
}
template <class T, enable_if_t<is_integral_v<T>, nullptr_t> = nullptr>
constexpr bool is_square(T n) {
	T s = sqrt(n);
	return s * s == n || (s + 1) * (s + 1) == n;
}
template <class T = long long> constexpr T BIT(int b) {
	return T(1) << b;
}
template <class T> constexpr int BIT(T x, int i) {
	return (x & (1 << i)) ? 1 : 0;
}
template <class T, class U, enable_if_t<is_integral_v<U>, nullptr_t> = nullptr>
constexpr T Pow(T a, U n) {
	assert(n >= 0);
	T result = 1;
	while (n > 0) {
		if (n & 1) {
			result *= a;
			n--;
		} else {
			a *= a;
			n >>= 1;
		}
	}
	return result;
}
template <class T, class U, enable_if_t<is_integral_v<U>, nullptr_t> = nullptr>
constexpr T Powmod(T a, U n, T mod) {
	assert(n >= 0);
	if (a > mod) a %= mod;
	T result = 1;
	while (n > 0) {
		if (n & 1) {
			result = result * a % mod;
			n--;
		} else {
			a = a * a % mod;
			n >>= 1;
		}
	}
	return result;
}
template <class T> bool chmax(T& a, const T& b) {
	if (a < b) {
		a = b;
		return true;
	}
	return false;
}
template <class T> bool chmin(T& a, const T& b) {
	if (a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T> int sz(const T& v) {
	return v.size();
}
template <class T, class U> int lower_index(const T& a, const U& v) {
	return lower_bound(all(a), v) - a.begin();
}
template <class T, class U> int upper_index(const T& a, const U& v) {
	return upper_bound(all(a), v) - a.begin();
}
template <class T> auto Slice(const T& v, size_t i, size_t len) {
	return i < v.size() ? T(v.begin() + i, v.begin() + min(i + len, v.size())) : T();
}
template <class T, class U = typename T::value_type> U Gcdv(const T& v) {
	return accumulate(next(v.begin()), v.end(), U(*v.begin()), gcd<U, U>);
}
template <class T, class U = typename T::value_type> U Lcmv(const T& v) {
	return accumulate(next(v.begin()), v.end(), U(*v.begin()), lcm<U, U>);
}
namespace internal {
	template <class T, size_t N> auto make_vector(vector<int>& sizes, const T& init) {
		if constexpr (N == 1) {
			return vector(sizes[0], init);
		} else {
			int size = sizes[N - 1];
			sizes.pop_back();
			return vector(size, make_vector<T, N - 1>(sizes, init));
		}
	}
}  // namespace internal
template <class T, size_t N>
auto make_vector(const int (&sizes)[N], const T& init = T()) {
	vector s(rbegin(sizes), rend(sizes));
	return internal::make_vector<T, N>(s, init);
}
#line 7 "/home/yuruhiya/programming/library/template/template_no_Ruby.cpp"
#if __has_include(<library/dump.hpp>)
#include <library/dump.hpp>
#define LOCAL
#else
#define dump(...) ((void)0)
#endif

template <class T> constexpr T oj_local(const T& oj, const T& local) {
#ifndef LOCAL
	return oj;
#else
	return local;
#endif
}
#line 5 "/home/yuruhiya/programming/library/Math/modint.cpp"
using namespace std;

template <int MOD> struct modint {
	using T = long long;
	T n;
	constexpr modint(const T x = 0) : n(x % MOD) {
		if (n < 0) n += MOD;
	}
	constexpr int get_mod() const {
		return MOD;
	}
	constexpr modint operator+() const {
		return *this;
	}
	constexpr modint operator-() const {
		return n ? MOD - n : 0;
	}
	constexpr modint& operator++() {
		if (MOD <= ++n) n = 0;
		return *this;
	}
	constexpr modint& operator--() {
		if (n <= 0) n = MOD;
		n--;
		return *this;
	}
	constexpr modint operator++(int) {
		modint t = *this;
		++*this;
		return t;
	}
	constexpr modint operator--(int) {
		modint t = *this;
		--*this;
		return t;
	}
	constexpr modint next() const {
		return ++modint(*this);
	}
	constexpr modint pred() const {
		return --modint(*this);
	}
	constexpr modint operator+(const modint& m) const {
		return modint(*this) += m;
	}
	constexpr modint operator-(const modint& m) const {
		return modint(*this) -= m;
	}
	constexpr modint operator*(const modint& m) const {
		return modint(*this) *= m;
	}
	constexpr modint operator/(const modint& m) const {
		return modint(*this) /= m;
	}
	constexpr modint& operator+=(const modint& m) {
		n += m.n;
		if (n >= MOD) n -= MOD;
		return *this;
	}
	constexpr modint& operator-=(const modint& m) {
		n -= m.n;
		if (n < 0) n += MOD;
		return *this;
	}
	constexpr modint& operator*=(const modint& m) {
		n = n * m.n % MOD;
		return *this;
	}
	constexpr modint& operator/=(const modint& m) {
		T a = m.n, b = MOD, u = 1, v = 0;
		while (b) {
			T t = a / b;
			a -= t * b;
			swap(a, b);
			u -= t * v;
			swap(u, v);
		}
		n = n * u % MOD;
		if (n < 0) n += MOD;
		return *this;
	}
	constexpr bool operator==(const modint& m) const {
		return n == m.n;
	}
	constexpr bool operator!=(const modint& m) const {
		return n != m.n;
	}
	template <class M> constexpr modint pow(M m) const {
		if (0 <= m) {
			modint t = n, result = 1;
			while (m > 0) {
				if (m & 1) {
					result *= t;
					m--;
				} else {
					t *= t;
					m >>= 1;
				}
			}
			return result;
		} else {
			return (modint(1) / n).pow(-m);
		}
	}
	template <class M> constexpr modint operator^(M m) const {
		return pow(m);
	}
	friend ostream& operator<<(ostream& os, const modint<MOD>& m) {
		return os << m.n;
	}
	friend istream& operator>>(istream& is, modint<MOD>& m) {
		long long x;
		cin >> x;
		m = modint(x);
		return is;
	}
};
using mint = modint<1000000007>;
using VM = vector<mint>;
mint operator""_m(unsigned long long n) {
	return n;
}
#line 4 "/home/yuruhiya/programming/library/Math/Combination.cpp"
using namespace std;

template <int MOD, size_t N> class Combination {
	using value_type = modint<MOD>;
	array<value_type, N + 1> fac, finv, inv;

public:
	constexpr Combination() {
		fac[0] = fac[1] = 1;
		finv[0] = finv[1] = 1;
		inv[1] = 1;
		for (size_t i = 2; i <= N; ++i) {
			fac[i] = fac[i - 1] * i;
			inv[i] = -inv[MOD % i] * (MOD / i);
			finv[i] = finv[i - 1] * inv[i];
		}
	}
	constexpr value_type P(int n, int r) const {
		return (n < r || n < 0 || r < 0) ? 0 : fac[n] * finv[n - r];
	}
	constexpr value_type C(int n, int r) const {
		return (n < r || n < 0 || r < 0) ? 0 : fac[n] * finv[r] * finv[n - r];
	}
	constexpr value_type H(int n, int r) const {
		return (n < 0 || r < 0) ? 0 : r == 0 ? 1 : C(n + r - 1, r);
	}
	constexpr value_type fact(int n) const {
		return fac[n];
	}
};
#line 3 "/home/yuruhiya/programming/library/Utility/CulSum.cpp"
#include <type_traits>
#line 5 "/home/yuruhiya/programming/library/Utility/CulSum.cpp"
using namespace std;

template <class T> class CulSum {
public:
	using value_type = T;
	using data_type = vector<value_type>;

private:
	size_t n;
	data_type data;

public:
	CulSum() = default;
	CulSum(const data_type& a) : n(a.size()), data(n + 1) {
		for (size_t i = 0; i < n; ++i) {
			data[i + 1] = data[i] + a[i];
		}
	}
	template <class U, class F, enable_if_t<is_integral_v<U>, nullptr_t> = nullptr>
	CulSum(const U& _n, F f) : n(_n), data(n + 1) {
		for (size_t i = 0; i < n; ++i) {
			data[i + 1] = data[i] + static_cast<value_type>(f(i));
		}
	}
	template <class U, class F, enable_if_t<!is_integral_v<U>, nullptr_t> = nullptr>
	CulSum(const U& a, F f)
	    : CulSum(a.size(), [a, f](size_t i) -> value_type { return f(a[i]); }) {}
	size_t size() const {
		return n;
	}
	value_type at(size_t i) const {
		return operator()(i, i + 1);
	}
	// [l, r)
	value_type operator()(size_t l, size_t r) const {
		l = min(l, n);
		r = min(r, n);
		return l > r ? 0 : data[r] - data[l];
	}
	// [0, r)
	value_type operator()(size_t r) const {
		r = min(r, n);
		return data[r];
	}
	const data_type& get_data() const {
		return data;
	}
};
#line 5 "a.cpp"

Combination<MOD, 500009> C;

int main() {
	ini(n, x);
	x = abs(x);
	ins(s);
	int cnt3 = count(all(s), 'S'), cnt5 = count(all(s), 'R') + count(all(s), 'P');

	CulSum<mint> sum5(cnt5 + 1,
	                  [&](int c) { return C.C(cnt5, c) * mint(2).pow(cnt5 - c); });
	mint ans = 0;
	rep(c, cnt3 + 1) {
		if (c % 2 != x % 2) continue;
		int need = x > c * 3 ? div_ceil(x - c * 3, 6) : 0;
		if (need > cnt5) continue;
		ans += C.C(cnt3, c) * mint(2).pow(cnt3 - c) * sum5(need, cnt5 + 1);
	}
	out(ans);
}
accuracy: 1
time_ms: 30
memory_kb: 19268
final_rank: 3

code_snippet: /**
 *    author:  otera    
**/
#include<bits/stdc++.h>
using namespace std;

#define int long long
typedef long long ll;
typedef long double ld;
const int inf=1e9+7;
const ll INF=1LL<<60;
#define rep(i, n) for(int i = 0; i < n; ++ i)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
#define fr first
#define sc second
#define all(c) c.begin(),c.end()
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

// modint: mod 計算を int を扱うように扱える構造体
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        return is >> x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

// 二項係数ライブラリ
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

const int MOD = 1000000007;
//const int MOD = 998244353;
using mint = Fp<MOD>;
BiCoef<mint> bc;

void solve() {
    int n, x; cin >> n >> x;
    string s; cin >> s;
    int cnts = 0, cntpr = 0;
    rep(i, n) {
        if(s[i] == 'S') ++ cnts;
        else ++ cntpr;
    }
    bc.init(6000600);
    vector<mint> sum(cntpr + 2, 0);
    for(int i = 0; i <= cntpr; ++ i) {
        sum[i + 1] = sum[i] + bc.com(cntpr, i) * modpow((mint)2, n - i);
    }
    mint ans = 0;
    for(int a = (x % 2 == 0 ? 0 : 1); a <= cnts; a += 2) {
        mint tmp;
        if(abs(x) <= 3 * a) {
            tmp = sum[cntpr + 1];
        } else {
            int bmi = (abs(x) - 3 * a + 5) / 6;
            tmp = sum[cntpr + 1] - sum.at(bmi);
        }
        ans += bc.com(cnts, a) * tmp / modpow((mint)2, a);
    }
    cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(20);
	//int t; cin >> t; rep(i, t)solve();
	solve();
    return 0;
}
accuracy: 0.11904761904761904
time_ms: 290
memory_kb: 146376
final_rank: 17

code_snippet: /**
 *    author:  otera    
**/
#include<bits/stdc++.h>
using namespace std;

#define int long long
typedef long long ll;
typedef long double ld;
const int inf=1e9+7;
const ll INF=1LL<<60;
#define rep(i, n) for(int i = 0; i < n; ++ i)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
#define fr first
#define sc second
#define all(c) c.begin(),c.end()
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

// modint: mod 計算を int を扱うように扱える構造体
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        return is >> x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

// 二項係数ライブラリ
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

const int MOD = 1000000007;
//const int MOD = 998244353;
using mint = Fp<MOD>;
BiCoef<mint> bc;

void solve() {
    int n, x; cin >> n >> x;
    string s; cin >> s;
    int cnts = 0, cntpr = 0;
    rep(i, n) {
        if(s[i] == 'S') ++ cnts;
        else ++ cntpr;
    }
    bc.init(6000600);
    vector<mint> sum(cntpr + 2, 0);
    for(int i = 0; i <= cntpr; ++ i) {
        sum[i + 1] = sum[i] + bc.com(cntpr, i) * modpow((mint)2, n - i);
    }
    mint ans = 0;
    for(int a = (x % 2 == 0 ? 0 : 1); a <= cnts; a += 2) {
        mint tmp;
        if(abs(x) <= 3 * a) {
            tmp = sum[cntpr + 1];
        } else {
            int bmi = (abs(x) - 3 * a + 5) / 6;
            if(bmi > cntpr + 1) continue;
            tmp = sum[cntpr + 1] - sum[bmi];
        }
        ans += bc.com(cnts, a) * tmp / modpow((mint)2, a);
    }
    cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(20);
	//int t; cin >> t; rep(i, t)solve();
	solve();
    return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 147708
final_rank: 13

code_snippet: /**
 *    author:  otera    
**/
#include<bits/stdc++.h>
using namespace std;

#define int long long
typedef long long ll;
typedef long double ld;
const int inf=1e9+7;
const ll INF=1LL<<60;
#define rep(i, n) for(int i = 0; i < n; ++ i)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
#define fr first
#define sc second
#define all(c) c.begin(),c.end()
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

// modint: mod 計算を int を扱うように扱える構造体
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        return is >> x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

// 二項係数ライブラリ
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

const int MOD = 1000000007;
//const int MOD = 998244353;
using mint = Fp<MOD>;
BiCoef<mint> bc;

void solve() {
    int n, x; cin >> n >> x;
    string s; cin >> s;
    int cnts = 0, cntpr = 0;
    rep(i, n) {
        if(s[i] == 'S') ++ cnts;
        else ++ cntpr;
    }
    bc.init(6000600);
    vector<mint> sum(cntpr + 2, 0);
    for(int i = 0; i <= cntpr; ++ i) {
        sum[i + 1] = sum[i] + bc.com(cntpr, i) * modpow((mint)2, n - i);
    }
    mint ans = 0;
    for(int a = (x % 2 == 0 ? 0 : 1); a <= cnts; a += 2) {
        mint tmp;
        if(abs(x) <= 3 * a) {
            tmp = sum[cntpr + 1];
        } else {
            int bmi = (abs(x) - 3 * a + 5) / 6;
            tmp = sum[cntpr + 1] - sum[bmi];
        }
        ans += bc.com(cnts, a) * tmp / modpow((mint)2, a);
    }
    cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(20);
	//int t; cin >> t; rep(i, t)solve();
	solve();
    return 0;
}
accuracy: 0.11904761904761904
time_ms: 290
memory_kb: 146388
final_rank: 18

code_snippet: /**
 *    author:  otera    
**/
#include<bits/stdc++.h>
using namespace std;

#define int long long
typedef long long ll;
typedef long double ld;
const int inf=1e9+7;
const ll INF=1LL<<60;
#define rep(i, n) for(int i = 0; i < n; ++ i)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
#define fr first
#define sc second
#define all(c) c.begin(),c.end()
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

// modint: mod 計算を int を扱うように扱える構造体
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        return is >> x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

// 二項係数ライブラリ
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

const int MOD = 1000000007;
//const int MOD = 998244353;
using mint = Fp<MOD>;
BiCoef<mint> bc;

void solve() {
    int n, x; cin >> n >> x;
    string s; cin >> s;
    int cnts = 0, cntpr = 0;
    rep(i, n) {
        if(s[i] == 'S') ++ cnts;
        else ++ cntpr;
    }
    bc.init(600600);
    vector<mint> sum(cntpr + 2, 0);
    for(int i = 0; i <= cntpr; ++ i) {
        sum[i + 1] = sum[i] + bc.com(cntpr, i) * modpow((mint)2, n - i);
    }
    mint ans = 0;
    for(int a = (x % 2 == 0 ? 0 : 1); a <= cnts; a += 2) {
        mint tmp;
        if(abs(x) <= 3 * a) {
            tmp = sum[cntpr + 1];
        } else {
            int bmi = (abs(x) - 3 * a + 5) / 6;
            tmp = sum[cntpr + 1] - sum[bmi];
        }
        ans += bc.com(cnts, a) * tmp / modpow((mint)2, a);
    }
    cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(20);
	//int t; cin >> t; rep(i, t)solve();
	solve();
    return 0;
}
accuracy: 0.11904761904761904
time_ms: 70
memory_kb: 19828
final_rank: 14

code_snippet: //
// Created by yamunaku on 2020/12/14.
//

#include <bits/stdc++.h>
//#include <atcoder/all>

using namespace std;
//using namespace atcoder;

#define rep(i, n) for(int i = 0; i < (n); i++)
#define repl(i, l, r) for(int i = (l); i < (r); i++)
#define per(i, n) for(int i = ((n)-1); i >= 0; i--)
#define perl(i, l, r) for(int i = ((r)-1); i >= (l); i--)
#define all(x) (x).begin(),(x).end()
#define MOD9 998244353
#define MOD 1000000007
#define IINF 1000000000
#define LINF 1000000000000000000
#define SP <<" "<<
#define CYES cout<<"Yes"<<endl
#define CNO cout<<"No"<<endl
#define CFS cin.tie(0);ios::sync_with_stdio(false)
#define CST(x) cout<<fixed<<setprecision(x)

using ll = long long;
using ld = long double;
using vi = vector<int>;
using mti = vector<vector<int>>;
using vl = vector<ll>;
using mtl = vector<vector<ll>>;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
template<typename T>
using heap = priority_queue<T, vector<T>, function<bool(const T, const T)>>;

ll modpow(ll x, ll a) {
    ll ans = 1;
    while (a) {
        if (a & 1) ans = ans * x % MOD;
        a >>= 1;
        x = x * x % MOD;
    }
    return ans;
}

ll inv(ll x) {
    return modpow(x, MOD - 2);
}

vector<ll> fact, invfact;

void buildFact(int n) {
    fact = vector<ll>(n + 1, 1);
    invfact = vector<ll>(n + 1, 1);
    for (int i = 1; i <= n; i++) {
        fact[i] = fact[i - 1] * i % MOD;
        invfact[i] = inv(fact[i]);
    }
}

ll comb(ll n, ll k) {
    return fact[n] * invfact[n - k] % MOD * invfact[k] % MOD;
}

int main() {
    //CFS;
    ll n, x;
    string s;
    cin >> n >> x >> s;
    x = abs(x);
    ll a3 = 0, a6 = 0;
    rep(i, n) {
        if (s[i] == 'S') a3++;
        else a6++;
    }
    ll ans = 0;
    vl c(a6 + 1);
    buildFact(n);
    rep(i, a6 + 1) {
        c[i] = comb(a6, i) * modpow(2, a6 - i) % MOD;
    }
    per(i, a6) {
        c[i] = (c[i] + c[i + 1]) % MOD;
    }
    rep(i, a3 + 1) {
        if (i % 2 != x % 2) continue;
        ll k = (max(0ll, x - 3 * i) + 5) / 6;
        if(k > a6) continue;
        ans += comb(a3, i) * modpow(2, a3 - i) % MOD * c[k] % MOD;
    }
    cout << ans % MOD << endl;
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 15340
final_rank: 10

code_snippet: //
// Created by yamunaku on 2020/12/14.
//

#include <bits/stdc++.h>
//#include <atcoder/all>

using namespace std;
//using namespace atcoder;

#define rep(i, n) for(int i = 0; i < (n); i++)
#define repl(i, l, r) for(int i = (l); i < (r); i++)
#define per(i, n) for(int i = ((n)-1); i >= 0; i--)
#define perl(i, l, r) for(int i = ((r)-1); i >= (l); i--)
#define all(x) (x).begin(),(x).end()
#define MOD9 998244353
#define MOD 1000000007
#define IINF 1000000000
#define LINF 1000000000000000000
#define SP <<" "<<
#define CYES cout<<"Yes"<<endl
#define CNO cout<<"No"<<endl
#define CFS cin.tie(0);ios::sync_with_stdio(false)
#define CST(x) cout<<fixed<<setprecision(x)

using ll = long long;
using ld = long double;
using vi = vector<int>;
using mti = vector<vector<int>>;
using vl = vector<ll>;
using mtl = vector<vector<ll>>;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
template<typename T>
using heap = priority_queue<T, vector<T>, function<bool(const T, const T)>>;

ll modpow(ll x, ll a) {
    ll ans = 1;
    while (a) {
        if (a & 1) ans = ans * x % MOD;
        a >>= 1;
        x = x * x % MOD;
    }
    return ans;
}

ll inv(ll x) {
    return modpow(x, MOD - 2);
}

vector<ll> fact, invfact;

void buildFact(int n) {
    fact = vector<ll>(n + 1, 1);
    invfact = vector<ll>(n + 1, 1);
    for (int i = 1; i <= n; i++) {
        fact[i] = fact[i - 1] * i % MOD;
        invfact[i] = inv(fact[i]);
    }
}

ll comb(ll n, ll k) {
    return fact[n] * invfact[n - k] % MOD * invfact[k] % MOD;
}

int main() {
    //CFS;
    ll n, x;
    string s;
    cin >> n >> x >> s;
    x = abs(x);
    ll a3 = 0, a6 = 0;
    rep(i, n) {
        if (s[i] == 'S') a3++;
        else a6++;
    }
    ll ans = 0;
    vl c(a6 + 1);
    buildFact(n);
    rep(i, a6 + 1) {
        c[i] = comb(a6, i) * modpow(2, a6 - i) % MOD;
    }
    per(i, a6) {
        c[i] = (c[i] + c[i + 1]) % MOD;
    }
    rep(i, a3 + 1) {
        if (i % 2 != x % 2) continue;
        ll k = (max(0ll, x - 3 * i) + 5) / 6;
        ans += comb(a3, i) * modpow(2, a3 - i) % MOD * c[k] % MOD;
    }
    cout << ans % MOD << endl;
    return 0;
}
accuracy: 0.11904761904761904
time_ms: 90
memory_kb: 13128
final_rank: 16

code_snippet: //
// Created by yamunaku on 2020/12/14.
//

#include <bits/stdc++.h>
//#include <atcoder/all>

using namespace std;
//using namespace atcoder;

#define rep(i, n) for(int i = 0; i < (n); i++)
#define repl(i, l, r) for(int i = (l); i < (r); i++)
#define per(i, n) for(int i = ((n)-1); i >= 0; i--)
#define perl(i, l, r) for(int i = ((r)-1); i >= (l); i--)
#define all(x) (x).begin(),(x).end()
#define MOD9 998244353
#define MOD 1000000007
#define IINF 1000000000
#define LINF 1000000000000000000
#define SP <<" "<<
#define CYES cout<<"Yes"<<endl
#define CNO cout<<"No"<<endl
#define CFS cin.tie(0);ios::sync_with_stdio(false)
#define CST(x) cout<<fixed<<setprecision(x)

using ll = long long;
using ld = long double;
using vi = vector<int>;
using mti = vector<vector<int>>;
using vl = vector<ll>;
using mtl = vector<vector<ll>>;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
template<typename T>
using heap = priority_queue<T, vector<T>, function<bool(const T, const T)>>;

ll modpow(ll x, ll a) {
    ll ans = 1;
    while (a) {
        if (a & 1) ans = ans * x % MOD;
        a >>= 1;
        x = x * x % MOD;
    }
    return ans;
}

ll inv(ll x) {
    return modpow(x, MOD - 2);
}

vector<ll> fact, invfact;

void buildFact(int n) {
    fact = vector<ll>(n + 1, 1);
    invfact = vector<ll>(n + 1, 1);
    for (int i = 1; i <= n; i++) {
        fact[i] = fact[i - 1] * i % MOD;
        invfact[i] = inv(fact[i]);
    }
}

ll comb(ll n, ll k) {
    return fact[n] * invfact[n - k] % MOD * invfact[k] % MOD;
}

int main() {
    //CFS;
    ll n, x;
    string s;
    cin >> n >> x >> s;
    x = abs(x);
    ll a3 = 0, a6 = 0;
    rep(i, n) {
        if (s[i] == 'S') a3++;
        else a6++;
    }
    ll ans = 0;
    vl c(a6 + 1);
    buildFact(n);
    rep(i, a6 + 1) {
        c[i] = comb(a6, i) * modpow(2, a6 - i);
    }
    per(i, a6) {
        c[i] = (c[i] + c[i + 1]) % MOD;
    }
    rep(i, a3 + 1) {
        if (i % 2 != x % 2) continue;
        ll k = (max(0ll, x - 3 * i) + 5) / 6;
        ans += comb(a3, i) * modpow(2, a3 - i) % MOD * c[k] % MOD;
    }
    cout << ans % MOD << endl;
    return 0;
}
accuracy: 0.11904761904761904
time_ms: 90
memory_kb: 13108
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
#include <math.h>
#include <iomanip>
#include <cstdint>
#include <string>
#include <sstream>
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
#define rep(i,n) for (int i = 0; i < (n); ++i)
typedef long long ll;
using P = pair<int,int>;

const int INF=1001001001;
const int mod =1e9+7;

struct mint {
  ll x; 
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
  mint operator+(const mint a) const { return mint(*this) += a;}
  mint operator-(const mint a) const { return mint(*this) -= a;}
  mint operator*(const mint a) const { return mint(*this) *= a;}
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }
   
  mint inv() const { return pow(mod-2);}
  mint& operator/=(const mint a) { return *this *= a.inv();}
  mint operator/(const mint a) const { return mint(*this) /= a;}
 };
  istream& operator>>(istream& is, const mint& a) { return is >> a.x;}
  ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}
  struct combination {
  vector<mint> fact, ifact;
  combination(int n):fact(n+1),ifact(n+1) {
    assert(n < mod);
    fact[0] = 1;
    for (int i = 1; i <= n; ++i) fact[i] = fact[i-1]*i;
    ifact[n] = fact[n].inv();
    for (int i = n; i >= 1; --i) ifact[i-1] = ifact[i]*i;
  }
  mint operator()(int n, int k) {
    if (k < 0 || k > n) return 0;
    return fact[n]*ifact[k]*ifact[n-k];
  }
 } c(500005);

int main() {
  ll N,X;
  string s;
  cin>>N>>X>>s;
  X=abs(X);
  map<char,ll>cnt;
  rep(i,N){
    cnt[s[i]]++;
  }
  ll C=cnt['S'];
  auto f=[&](int p){
    return c(C,p)*mint(2).pow(C-p);
  };
  auto f2=[&](int q){
    return c(N-C,q)*mint(2).pow(N-C-q);
  };
  vector<mint>sumq(500005);
  for(int i=0;i<=N-C;i++){
    sumq[i+1]=sumq[i]+f2(i);
  }
  mint ans=0;
  rep(p,C+1){
    if((3*p)%2!=X%2){continue;}
    if(p*3+(N-C)*6<X){continue;}
    mint v=f(p);
    ans+=v*(sumq[N-C+1]-sumq[max(0ll,(X-3*p+5)/6)]);
  }
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 15488
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
#include <math.h>
#include <iomanip>
#include <cstdint>
#include <string>
#include <sstream>
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
#define rep(i,n) for (int i = 0; i < (n); ++i)
typedef long long ll;
using P = pair<int,int>;

const int INF=1001001001;
const int mod =1e9+7;

struct mint {
  ll x; 
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
  mint operator+(const mint a) const { return mint(*this) += a;}
  mint operator-(const mint a) const { return mint(*this) -= a;}
  mint operator*(const mint a) const { return mint(*this) *= a;}
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }
   
  mint inv() const { return pow(mod-2);}
  mint& operator/=(const mint a) { return *this *= a.inv();}
  mint operator/(const mint a) const { return mint(*this) /= a;}
 };
  istream& operator>>(istream& is, const mint& a) { return is >> a.x;}
  ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}
  struct combination {
  vector<mint> fact, ifact;
  combination(int n):fact(n+1),ifact(n+1) {
    assert(n < mod);
    fact[0] = 1;
    for (int i = 1; i <= n; ++i) fact[i] = fact[i-1]*i;
    ifact[n] = fact[n].inv();
    for (int i = n; i >= 1; --i) ifact[i-1] = ifact[i]*i;
  }
  mint operator()(int n, int k) {
    if (k < 0 || k > n) return 0;
    return fact[n]*ifact[k]*ifact[n-k];
  }
 } c(500005);

int main() {
  int N,X;
  string s;
  cin>>N>>X>>s;
  X=abs(X);
  map<char,int>cnt;
  rep(i,N){
    cnt[s[i]]++;
  }
  int C=cnt['S'];
  auto f=[&](int p){
    return c(C,p)*mint(2).pow(C-p);
  };
  auto f2=[&](int q){
    return c(N-C,q)*mint(2).pow(N-C-q);
  };
  vector<mint>sumq(500005);
  rep(i,N-C+1){
    sumq[i+1]=sumq[i]+f2(i);
  }
  mint ans=0;
  rep(p,C+1){
    if(p%2!=X%2){continue;}
    if(p*3+(N-C)*6<X){continue;}
    mint v=f(p);
    ans+=v*(sumq[N-C+1]-sumq[(X-3*p)/6+((X-3*p)%6!=0)]);
  }
  cout<<ans<<endl;
  return 0;
}
accuracy: 0.07142857142857142
time_ms: 20
memory_kb: 15212
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
#include <math.h>
#include <iomanip>
#include <cstdint>
#include <string>
#include <sstream>
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
#define rep(i,n) for (int i = 0; i < (n); ++i)
typedef long long ll;
using P = pair<int,int>;

const int INF=1001001001;
const int mod =1e9+7;

struct mint {
  ll x; 
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
  mint operator+(const mint a) const { return mint(*this) += a;}
  mint operator-(const mint a) const { return mint(*this) -= a;}
  mint operator*(const mint a) const { return mint(*this) *= a;}
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }
   
  mint inv() const { return pow(mod-2);}
  mint& operator/=(const mint a) { return *this *= a.inv();}
  mint operator/(const mint a) const { return mint(*this) /= a;}
 };
  istream& operator>>(istream& is, const mint& a) { return is >> a.x;}
  ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}
  struct combination {
  vector<mint> fact, ifact;
  combination(int n):fact(n+1),ifact(n+1) {
    assert(n < mod);
    fact[0] = 1;
    for (int i = 1; i <= n; ++i) fact[i] = fact[i-1]*i;
    ifact[n] = fact[n].inv();
    for (int i = n; i >= 1; --i) ifact[i-1] = ifact[i]*i;
  }
  mint operator()(int n, int k) {
    if (k < 0 || k > n) return 0;
    return fact[n]*ifact[k]*ifact[n-k];
  }
 } c(500005);

int main() {
  int N,X;
  string s;
  cin>>N>>X>>s;
  X=abs(X);
  map<char,int>cnt;
  rep(i,N){
    cnt[s[i]]++;
  }
  int C=cnt['S'];
  auto f=[&](int p){
    return c(C,p)*mint(2).pow(C-p);
  };
  auto f2=[&](int q){
    return c(N-C,q)*mint(2).pow(N-C-q);
  };
  vector<mint>sumq(500005);
  rep(i,N-C+1){
    sumq[i+1]=sumq[i]+f2(i);
  }
  mint ans=0;
  rep(p,C+1){
    if(p%2!=X%2){continue;}
    if(p*3+(N-C)*6<X){continue;}
    ans+=f(p)*(sumq[N-C+1]-sumq[(X-3*p)/6+((X-3*p)%6!=0)]);
  }
  cout<<ans<<endl;
  return 0;
}
accuracy: 0.07142857142857142
time_ms: 20
memory_kb: 15104
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using lint = long long;
using pint = pair<int, int>;
using plint = pair<lint, lint>;
struct fast_ios { fast_ios(){ cin.tie(nullptr), ios::sync_with_stdio(false), cout << fixed << setprecision(20); }; } fast_ios_;
#define ALL(x) (x).begin(), (x).end()
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define IFOR(i, begin, end) for(int i=(end)-1,i##_begin_=(begin);i>=i##_begin_;i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)
template <typename T, typename V>
void ndarray(vector<T>& vec, const V& val, int len) { vec.assign(len, val); }
template <typename T, typename V, typename... Args> void ndarray(vector<T>& vec, const V& val, int len, Args... args) { vec.resize(len), for_each(begin(vec), end(vec), [&](T& v) { ndarray(v, val, args...); }); }
template <typename T> bool chmax(T &m, const T q) { if (m < q) {m = q; return true;} else return false; }
template <typename T> bool chmin(T &m, const T q) { if (m > q) {m = q; return true;} else return false; }
int floor_lg(long long x) { return x <= 0 ? -1 : 63 - __builtin_clzll(x); }
template <typename T1, typename T2> pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first + r.first, l.second + r.second); }
template <typename T1, typename T2> pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first - r.first, l.second - r.second); }
template <typename T> vector<T> sort_unique(vector<T> vec) { sort(vec.begin(), vec.end()), vec.erase(unique(vec.begin(), vec.end()), vec.end()); return vec; }
template <typename T> istream &operator>>(istream &is, vector<T> &vec) { for (auto &v : vec) is >> v; return is; }
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) { os << '['; for (auto v : vec) os << v << ','; os << ']'; return os; }
template <typename T, size_t sz> ostream &operator<<(ostream &os, const array<T, sz> &arr) { os << '['; for (auto v : arr) os << v << ','; os << ']'; return os; }
#if __cplusplus >= 201703L
template <typename... T> istream &operator>>(istream &is, tuple<T...> &tpl) { std::apply([&is](auto &&... args) { ((is >> args), ...);}, tpl); return is; }
template <typename... T> ostream &operator<<(ostream &os, const tuple<T...> &tpl) { std::apply([&os](auto &&... args) { ((os << args << ','), ...);}, tpl); return os; }
#endif
template <typename T> ostream &operator<<(ostream &os, const deque<T> &vec) { os << "deq["; for (auto v : vec) os << v << ','; os << ']'; return os; }
template <typename T> ostream &operator<<(ostream &os, const set<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T, typename TH> ostream &operator<<(ostream &os, const unordered_set<T, TH> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T> ostream &operator<<(ostream &os, const multiset<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T> ostream &operator<<(ostream &os, const unordered_multiset<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &pa) { os << '(' << pa.first << ',' << pa.second << ')'; return os; }
template <typename TK, typename TV> ostream &operator<<(ostream &os, const map<TK, TV> &mp) { os << '{'; for (auto v : mp) os << v.first << "=>" << v.second << ','; os << '}'; return os; }
template <typename TK, typename TV, typename TH> ostream &operator<<(ostream &os, const unordered_map<TK, TV, TH> &mp) { os << '{'; for (auto v : mp) os << v.first << "=>" << v.second << ','; os << '}'; return os; }
#ifdef HITONANODE_LOCAL
const string COLOR_RESET = "\033[0m", BRIGHT_GREEN = "\033[1;32m", BRIGHT_RED = "\033[1;31m", BRIGHT_CYAN = "\033[1;36m", NORMAL_CROSSED = "\033[0;9;37m", RED_BACKGROUND = "\033[1;41m", NORMAL_FAINT = "\033[0;2m";
#define dbg(x) cerr << BRIGHT_CYAN << #x << COLOR_RESET << " = " << (x) << NORMAL_FAINT << " (L" << __LINE__ << ") " << __FILE__ << COLOR_RESET << endl
#else
#define dbg(x) {}
#endif

template <int mod> struct ModInt {
#if __cplusplus >= 201402L
#define MDCONST constexpr
#else
#define MDCONST
#endif
    using lint = long long;
    MDCONST static int get_mod() { return mod; }
    static int get_primitive_root() {
        static int primitive_root = 0;
        if (!primitive_root) {
            primitive_root = [&]() {
                std::set<int> fac;
                int v = mod - 1;
                for (lint i = 2; i * i <= v; i++)
                    while (v % i == 0) fac.insert(i), v /= i;
                if (v > 1) fac.insert(v);
                for (int g = 1; g < mod; g++) {
                    bool ok = true;
                    for (auto i : fac)
                        if (ModInt(g).pow((mod - 1) / i) == 1) {
                            ok = false;
                            break;
                        }
                    if (ok) return g;
                }
                return -1;
            }();
        }
        return primitive_root;
    }
    int val;
    MDCONST ModInt() : val(0) {}
    MDCONST ModInt &_setval(lint v) { return val = (v >= mod ? v - mod : v), *this; }
    MDCONST ModInt(lint v) { _setval(v % mod + mod); }
    MDCONST explicit operator bool() const { return val != 0; }
    MDCONST ModInt operator+(const ModInt &x) const { return ModInt()._setval((lint)val + x.val); }
    MDCONST ModInt operator-(const ModInt &x) const { return ModInt()._setval((lint)val - x.val + mod); }
    MDCONST ModInt operator*(const ModInt &x) const { return ModInt()._setval((lint)val * x.val % mod); }
    MDCONST ModInt operator/(const ModInt &x) const { return ModInt()._setval((lint)val * x.inv() % mod); }
    MDCONST ModInt operator-() const { return ModInt()._setval(mod - val); }
    MDCONST ModInt &operator+=(const ModInt &x) { return *this = *this + x; }
    MDCONST ModInt &operator-=(const ModInt &x) { return *this = *this - x; }
    MDCONST ModInt &operator*=(const ModInt &x) { return *this = *this * x; }
    MDCONST ModInt &operator/=(const ModInt &x) { return *this = *this / x; }
    friend MDCONST ModInt operator+(lint a, const ModInt &x) { return ModInt()._setval(a % mod + x.val); }
    friend MDCONST ModInt operator-(lint a, const ModInt &x) { return ModInt()._setval(a % mod - x.val + mod); }
    friend MDCONST ModInt operator*(lint a, const ModInt &x) { return ModInt()._setval(a % mod * x.val % mod); }
    friend MDCONST ModInt operator/(lint a, const ModInt &x) { return ModInt()._setval(a % mod * x.inv() % mod); }
    MDCONST bool operator==(const ModInt &x) const { return val == x.val; }
    MDCONST bool operator!=(const ModInt &x) const { return val != x.val; }
    MDCONST bool operator<(const ModInt &x) const { return val < x.val; } // To use std::map<ModInt, T>
    friend std::istream &operator>>(std::istream &is, ModInt &x) {
        lint t;
        return is >> t, x = ModInt(t), is;
    }
    MDCONST friend std::ostream &operator<<(std::ostream &os, const ModInt &x) { return os << x.val; }
    MDCONST ModInt pow(lint n) const {
        lint ans = 1, tmp = this->val;
        while (n) {
            if (n & 1) ans = ans * tmp % mod;
            tmp = tmp * tmp % mod, n /= 2;
        }
        return ans;
    }

    static std::vector<long long> facs, invs;
    MDCONST static void _precalculation(int N) {
        int l0 = facs.size();
        if (N <= l0) return;
        facs.resize(N), invs.resize(N);
        for (int i = l0; i < N; i++) facs[i] = facs[i - 1] * i % mod;
        long long facinv = ModInt(facs.back()).pow(mod - 2).val;
        for (int i = N - 1; i >= l0; i--) {
            invs[i] = facinv * facs[i - 1] % mod;
            facinv = facinv * i % mod;
        }
    }
    MDCONST lint inv() const {
        if (this->val < 1 << 20) {
            while (this->val >= int(facs.size())) _precalculation(facs.size() * 2);
            return invs[this->val];
        } else {
            return this->pow(mod - 2).val;
        }
    }
    MDCONST ModInt fac() const {
        while (this->val >= int(facs.size())) _precalculation(facs.size() * 2);
        return facs[this->val];
    }

    MDCONST ModInt doublefac() const {
        lint k = (this->val + 1) / 2;
        return (this->val & 1) ? ModInt(k * 2).fac() / (ModInt(2).pow(k) * ModInt(k).fac()) : ModInt(k).fac() * ModInt(2).pow(k);
    }
    MDCONST ModInt nCr(const ModInt &r) const { return (this->val < r.val) ? 0 : this->fac() / ((*this - r).fac() * r.fac()); }

    ModInt sqrt() const {
        if (val == 0) return 0;
        if (mod == 2) return val;
        if (pow((mod - 1) / 2) != 1) return 0;
        ModInt b = 1;
        while (b.pow((mod - 1) / 2) == 1) b += 1;
        int e = 0, m = mod - 1;
        while (m % 2 == 0) m >>= 1, e++;
        ModInt x = pow((m - 1) / 2), y = (*this) * x * x;
        x *= (*this);
        ModInt z = b.pow(m);
        while (y != 1) {
            int j = 0;
            ModInt t = y;
            while (t != 1) j++, t *= t;
            z = z.pow(1LL << (e - j - 1));
            x *= z, z *= z, y *= z;
            e = j;
        }
        return ModInt(std::min(x.val, mod - x.val));
    }
};
template <int mod> std::vector<long long> ModInt<mod>::facs = {1};
template <int mod> std::vector<long long> ModInt<mod>::invs = {0};
using mint = ModInt<1000000007>;

// Integer convolution for arbitrary mod
// with NTT (and Garner's algorithm) for ModInt / ModIntRuntime class.
// We skip Garner's algorithm if `skip_garner` is true or mod is in `nttprimes`.
// input: a (size: n), b (size: m)
// return: vector (size: n + m - 1)
template <typename MODINT> std::vector<MODINT> nttconv(std::vector<MODINT> a, std::vector<MODINT> b, bool skip_garner = false);

constexpr int nttprimes[3] = {998244353, 167772161, 469762049};

// Integer FFT (Fast Fourier Transform) for ModInt class
// (Also known as Number Theoretic Transform, NTT)
// is_inverse: inverse transform
// ** Input size must be 2^n **
template <typename MODINT> void ntt(std::vector<MODINT> &a, bool is_inverse = false) {
    int n = a.size();
    if (n == 1) return;
    static const int mod = MODINT::get_mod();
    static const MODINT root = MODINT::get_primitive_root();
    assert(__builtin_popcount(n) == 1 and (mod - 1) % n == 0);

    static std::vector<MODINT> w{1}, iw{1};
    for (int m = w.size(); m < n / 2; m *= 2) {
        MODINT dw = root.pow((mod - 1) / (4 * m)), dwinv = 1 / dw;
        w.resize(m * 2), iw.resize(m * 2);
        for (int i = 0; i < m; i++) w[m + i] = w[i] * dw, iw[m + i] = iw[i] * dwinv;
    }

    if (!is_inverse) {
        for (int m = n; m >>= 1;) {
            for (int s = 0, k = 0; s < n; s += 2 * m, k++) {
                for (int i = s; i < s + m; i++) {
                    MODINT x = a[i], y = a[i + m] * w[k];
                    a[i] = x + y, a[i + m] = x - y;
                }
            }
        }
    } else {
        for (int m = 1; m < n; m *= 2) {
            for (int s = 0, k = 0; s < n; s += 2 * m, k++) {
                for (int i = s; i < s + m; i++) {
                    MODINT x = a[i], y = a[i + m];
                    a[i] = x + y, a[i + m] = (x - y) * iw[k];
                }
            }
        }
        int n_inv = MODINT(n).inv();
        for (auto &v : a) v *= n_inv;
    }
}
template <int MOD> std::vector<ModInt<MOD>> nttconv_(const std::vector<int> &a, const std::vector<int> &b) {
    int sz = a.size();
    assert(a.size() == b.size() and __builtin_popcount(sz) == 1);
    std::vector<ModInt<MOD>> ap(sz), bp(sz);
    for (int i = 0; i < sz; i++) ap[i] = a[i], bp[i] = b[i];
    ntt(ap, false);
    if (a == b)
        bp = ap;
    else
        ntt(bp, false);
    for (int i = 0; i < sz; i++) ap[i] *= bp[i];
    ntt(ap, true);
    return ap;
}
long long garner_ntt_(int r0, int r1, int r2, int mod) {
    using mint2 = ModInt<nttprimes[2]>;
    static const long long m01 = 1LL * nttprimes[0] * nttprimes[1];
    static const long long m0_inv_m1 = ModInt<nttprimes[1]>(nttprimes[0]).inv();
    static const long long m01_inv_m2 = mint2(m01).inv();

    int v1 = (m0_inv_m1 * (r1 + nttprimes[1] - r0)) % nttprimes[1];
    auto v2 = (mint2(r2) - r0 - mint2(nttprimes[0]) * v1) * m01_inv_m2;
    return (r0 + 1LL * nttprimes[0] * v1 + m01 % mod * v2.val) % mod;
}
template <typename MODINT> std::vector<MODINT> nttconv(std::vector<MODINT> a, std::vector<MODINT> b, bool skip_garner) {
    int sz = 1, n = a.size(), m = b.size();
    while (sz < n + m) sz <<= 1;
    if (sz <= 16) {
        std::vector<MODINT> ret(n + m - 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) ret[i + j] += a[i] * b[j];
        }
        return ret;
    }
    int mod = MODINT::get_mod();
    if (skip_garner or std::find(std::begin(nttprimes), std::end(nttprimes), mod) != std::end(nttprimes)) {
        a.resize(sz), b.resize(sz);
        if (a == b) {
            ntt(a, false);
            b = a;
        } else
            ntt(a, false), ntt(b, false);
        for (int i = 0; i < sz; i++) a[i] *= b[i];
        ntt(a, true);
        a.resize(n + m - 1);
    } else {
        std::vector<int> ai(sz), bi(sz);
        for (int i = 0; i < n; i++) ai[i] = a[i].val;
        for (int i = 0; i < m; i++) bi[i] = b[i].val;
        auto ntt0 = nttconv_<nttprimes[0]>(ai, bi);
        auto ntt1 = nttconv_<nttprimes[1]>(ai, bi);
        auto ntt2 = nttconv_<nttprimes[2]>(ai, bi);
        a.resize(n + m - 1);
        for (int i = 0; i < n + m - 1; i++) { a[i] = garner_ntt_(ntt0[i].val, ntt1[i].val, ntt2[i].val, mod); }
    }
    return a;
}

int main()
{
    int N, X;
    string S;
    cin >> N >> X >> S;
    X = abs(X);
    const int w3 = count(S.begin(), S.end(), 'S'), w6 = N - w3;

    vector<mint> v3(w3 + 1), v6(w6 * 2 + 1);
    REP(i, w3 + 1) v3[i] = mint(w3).nCr(i) * mint(2).pow(w3 - i);
    REP(i, w6 + 1) v6[i * 2] = mint(w6).nCr(i) * mint(2).pow(w6 - i);

    vector<mint> cv = nttconv(v3, v6);

    mint ret = 0;
    REP(i, cv.size()) {
        int y = i * 3 - X;
        if (y >= 0 and y % 2 == 0) ret += cv[i];
    }
    cout << ret << '\n';
}
accuracy: 1
time_ms: 320
memory_kb: 104540
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ALL(x) begin(x),end(x)
#define rep(i,n) for(int i=0;i<(n);i++)
#define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl;
#define mod 1000000007
using ll=long long;
const int INF=1000000000;
const ll LINF=1001002003004005006ll;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
// ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;}

struct IOSetup{
    IOSetup(){
        cin.tie(0);
        ios::sync_with_stdio(0);
        cout<<fixed<<setprecision(12);
    }
} iosetup;
 
template<typename T>
ostream &operator<<(ostream &os,const vector<T>&v){
    for(int i=0;i<(int)v.size();i++) os<<v[i]<<(i+1==(int)v.size()?"":" ");
    return os;
}
template<typename T>
istream &operator>>(istream &is,vector<T>&v){
    for(T &x:v)is>>x;
    return is;
}

template<ll Mod>
struct ModInt{
    long long x;
    ModInt():x(0){}
    ModInt(long long y):x(y>=0?y%Mod:(Mod-(-y)%Mod)%Mod){}
    ModInt &operator+=(const ModInt &p){
        if((x+=p.x)>=Mod) x-=Mod;
        return *this;
    }
    ModInt &operator-=(const ModInt &p){
        if((x+=Mod-p.x)>=Mod)x-=Mod;
        return *this;
    }
    ModInt &operator*=(const ModInt &p){
        x=(int)(1ll*x*p.x%Mod);
        return *this;
    }
    ModInt &operator/=(const ModInt &p){
        (*this)*=p.inverse();
        return *this;
    }
    ModInt operator-()const{return ModInt(-x);}
    ModInt operator+(const ModInt &p)const{return ModInt(*this)+=p;}
    ModInt operator-(const ModInt &p)const{return ModInt(*this)-=p;}
    ModInt operator*(const ModInt &p)const{return ModInt(*this)*=p;}
    ModInt operator/(const ModInt &p)const{return ModInt(*this)/=p;}
    bool operator==(const ModInt &p)const{return x==p.x;}
    bool operator!=(const ModInt &p)const{return x!=p.x;}
    ModInt inverse()const{
        int a=x,b=Mod,u=1,v=0,t;
        while(b>0){
            t=a/b;
            swap(a-=t*b,b);swap(u-=t*v,v);
        }
        return ModInt(u);
    }
    ModInt pow(long long n)const{
        ModInt ret(1),mul(x);
        while(n>0){
            if(n&1) ret*=mul;
            mul*=mul;n>>=1;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &os,const ModInt &p){return os<<p.x;}
    friend istream &operator>>(istream &is,ModInt &a){long long t;is>>t;a=ModInt<Mod>(t);return (is);}
    static int get_mod(){return Mod;}
};
using mint=ModInt<mod>;

template<int MAX>
struct comcalc{
    vector<mint> fact,finv,inv;
    comcalc():fact(MAX),finv(MAX),inv(MAX){
        fact[0]=mint(1),fact[1]=mint(1),finv[0]=mint(1),finv[1]=mint(1),inv[1]=mint(1);
        for(int i=2;i<MAX;i++){
            fact[i]=fact[i-1]*mint(i);
            inv[i]=mint(0)-inv[mod%i]*(mint(mod/i));
            finv[i]=finv[i-1]*inv[i];
        }
    }
    mint com(int n,int k){
        if(n<k) return mint(0);
        if(n<0 or k<0) return mint(0);
        return fact[n]*(finv[k]*finv[n-k]);
    }
    mint fac(int n){
        return fact[n];
    }
    // 重複組み合わせ:n種類の物から重複を許し，k個選ぶ
    mint nHk(int n,int k){
        return com(n+k-1,k);
    }
    // 玉n区別，箱k区別，各箱1個以上O(k)
    mint F12_dis_dis_one(int n,int k){
        if(n<k)return mint(0);
        mint ret=0;
        for(int i=0;i<=k;i++){
            mint add=com(k,i)*(mint(i).pow(n));
            if((k-i)%2) ret-=add;
            else        ret+=add;
        }
        return ret;
    }
    /* sum combination(n+x, x), x=l to r
       https://www.wolframalpha.com/input/?i=sum+combination%28n%2Bx+%2Cx%29%2C+x%3Dl+to+r&lang=ja 
       check n+x < [COM_PRECALC_MAX]    */
    mint sum_of_comb(int n,int l,int r){
        if(l>r)return mint(0);
        mint ret=mint(r+1)*com(n+r+1,r+1)-mint(l)*com(l+n,l);
        ret/=mint(n+1);
        return ret;
    }
};


/*

奇数回グーで勝つ必要があるか
何回グーで勝つかで探索して頑張る
*/

signed main(){
    comcalc<2000000> F;

    int n,x;cin>>n>>x;x=abs(x);
    string s;cin>>s;

    int gcnt=0;
    for(auto &c:s)gcnt+=(c=='S');
    int spcnt=n-gcnt;

    vector<mint> pre(spcnt+1);
    rep(i,spcnt+1) pre[i]=F.com(spcnt,i)*mint(2).pow(spcnt-i);
    for(int i=spcnt-1;i>=0;i--){
        pre[i]+=pre[i+1];
    }


    mint res=0;
    for(int i=x%2;i<=gcnt;i+=2){
        int d=max(0,x-3*i);

        int need=(d+5)/6;
        if(need>spcnt) continue;

        // gcnt-i回負けるか引き分ける
        mint add=1;
        add*=F.com(gcnt,i);// 勝つ場所を選ぶ
        add*=mint(2).pow(gcnt-i);// 負けるか引き分ける

        // // naive
        // mint add2=0;
        // for(int j=need;j<=spcnt;j++){
        //     add2+=F.com(spcnt,j)*mint(2).pow(spcnt-j);
        // }
        mint add2=pre[need];

        res+=add*add2;
    }
    cout<<res<<endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 54236
final_rank: 11