#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define endl "\n" #define ll long long #define ch char #define vec vector #define vll vector #define sll set #define pll pair #define mkp make_pair #define mll map #define puf push_front #define pub push_back #define pof pop_front() #define pob pop_back() #define em empty() #define fi first #define se second #define fr front() #define ba back() #define be begin() #define rbe rbegin() #define en end() #define ren rend() #define all(x) x.begin(),x.end() #define rall(x) x.rbegin(),x.rend() #define fo(i,x,y) for(ll i=x;i<=y;++i) #define fa(i,v) for(auto &i:v) #define re return #define sz size() #define so(v) sort(all(v)) #define pop_count(x) __builtin_popcount(x) #define rso(v) sort(rall(v)) #define rev(v) reverse(all(v)) #define i(x) for(ll i=0;i void ff(T a,A... b){ cout< void cc(T a,A... b){ cout< void cl(T a,A... b){ cout< void cn(T a,A... b){ cout< void ci(A&... a){ (cin>>...>>a); }; templatevoid ou(T v){fa(i,v)cout<void oun(T v){fa(i,v)cout<void ouu(T v){fa(i,v){fa(j,i)cout< void oul(T v){fa(i,v)cout<void in(T &v){fa(i,v)cin>>i;} templatevoid inn(T &v){fa(i,v)fa(j,i)cin>>j;} templatevoid oump(T &v){fa(i,v)ff(i.fi,i.se);} templatevoid pi(pair &p){ci(p.fi,p.se);} templatevoid po(pair &p){ff(p.fi,p.se);} template void fl(T a,A... b){ cout< dist1(1.0, 100000); i(10000){ // 各分布法に基いて乱数を生成 ll n = dist1(engine); } return 0; } */ mll to_prime(ll x){ mll mp; for(ll i=2;i*i<=x;++i){ while(x%i==0){ ++mp[i]; x/=i; } } if(x!=1) ++mp[x]; re mp; } #define acc(v) accumulate(v.begin(),v.end(),0LL) #define acci(v,i) accumulate(v.begin(),v.begin()+i,0LL) #define dll deque int main(void){ init(); solve(); return 0; } template class pnt{ public: T x,y; pnt(T x=0,T y=0):x(x),y(y){} pnt operator + (const pnt r)const { return pnt(x+r.x,y+r.y);} pnt operator - (const pnt r)const { return pnt(x-r.x,y-r.y);} pnt operator * (const pnt r)const { return pnt(x*r.x,y*r.y);} pnt operator / (const pnt r)const { return pnt(x/r.x,y/r.y);} pnt &operator += (const pnt r){ x+=r.x;y+=r.y;return *this;} pnt &operator -= (const pnt r){ x-=r.x;y-=r.y;return *this;} pnt &operator *= (const pnt r){ x*=r.x;y*=r.y;return *this;} pnt &operator /= (const pnt r){ x/=r.x;y/=r.y;return *this;} ll dist(const pnt r){ re (x-r.x)*(x-r.x)+(y-r.y)*(y-r.y); } ll man(const pnt r){ re abs(x-r.x)+abs(y-r.y); } pnt rot(const dou theta){ T xx,yy; xx=cos(theta)*x-sin(theta)*y; yy=sin(theta)*x+cos(theta)*y; return pnt(xx,yy); } }; istream &operator >> (istream &is,pnt &r){is>>r.x>>r.y;return is;} ostream &operator << (ostream &os,pnt &r){os<bool chmaxeq(T& a, const T& b) { if (a <= b) { a = b; return 1; } return 0; } templatebool chmineq(T& a, const T& b) { if (b <= a) { a = b; return 1; } return 0; } templatebool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; } templatebool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; } struct Trie{ struct Node{ vll nxt; vec done; ll dep,cnt=0; Node(ll c_):nxt(30),dep(c_){} }; ll root=0; vectree={Node(root)}; void ins(st s){ ll c=0; for(ll i=0;i1)++ans; else break; c=to; } re ans; } }; #define fo(i,x,y) for(ll i=x;i<=y;++i) #define rfo(_ii,_xx,_yy) for(ll _ii=_xx;_ii>=_yy;--_ii) #define qll queue template using pq= priority_queue; template using pqg= priority_queue,greater>; vec>rle(st s){//run_length_encoding ll n=s.sz; vec>ans; for(ll i=0;i> mat_mul(vector> a, vector> b, ll mod) { // 行列乗算 int n = a.size(); vector> res(n, vector(n)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++) { res[i][j] += a[i][k] * b[k][j]; res[i][j] %= mod; } } } return res; } vector> mat_pow(vector> a, ll b, ll mod) { // 行列累乗 int n = a.size(); vector> res(n, vector(n)); for (int i = 0; i < n; i++) res[i][i] = 1; while (b) { if (b & 1) res = mat_mul(res, a, mod); a = mat_mul(a, a, mod); b >>= 1; } return res; } void Yes(bool f){ ff(f?"Yes":"No");re; } void yes(bool f){ ff(f?"yes":"no");re; } void YES(bool f){ ff(f?"YES":"NO");re; } void sub(); void solve(){ //ge(ll,t); ll t=1; xx(t){ sub(); } } template struct Edge { int rv, from, to; // rev:逆向きの辺の番号 T cap, original_cap; Edge(int f, int t, T c,int r ) : rv(r), from(f), to(t), cap(c), original_cap(c) {} }; template struct Graph { vector>> G; Graph(int n = 0) : G(n) {} vector>& operator[](int i) { return G[i]; }//G[i]でi番目の辺を返す const size_t size() const { return G.size(); }// Edge& redge(Edge e) { // 逆向きの辺を返す return G[e.to][e.rv]; // 自己ループはないと仮定(あれば G[e.to][e.rev + 1] とする必要がある) } void add_edg(int from, int to, T cap) { // 有向辺を加える G[from].push_back( Edge( from, to, cap,(int)G[to].size() )); G[to].push_back(Edge( to, from, 0 ,(int)G[from].size() - 1)); } }; /* FordFulkerson: Ford-Fulkersonのアルゴリズムで最大流を求める構造体 max_flow(G,s,t):sからtへのグラフGの最大流を求める 副作用:G は最大流の残余ネットワークになる 計算量: O(|f*||E|) (f*:最大流) (この最悪ケースになることはほぼ無い) */ template struct Ford { const T INF = 1e9; vector used; Ford(){}; T dfs(Graph& G, int v, int t, T f) { // 増加可能経路を見つけて増加分のフローを返す if (v == t) return f; used[v] = true; for (auto& e : G[v]) { if (!used[e.to] && e.cap > 0) { T d = dfs(G, e.to, t, min(f, e.cap)); if (d > 0) { e.cap -= d; G.redge(e).cap += d; return d; } } } return 0; } T max_flow(Graph& G, int s, int t) { T flow = 0; while (true) { used.assign(G.size(), 0); T f = dfs(G, s, t, INF); // f が増加分のフロー if (f == 0) { return flow; } else { flow += f; } } return 0; } /* Fordf; ff(f.max_flow(g,s,sink)); */ }; struct UF{ vll par,rk,siz; UF(ll n):par(n+5,-1),rk(n+5,0){ } ll root(ll x){ if(par[x]<0)return x; else return par[x]=root(par[x]); } bool same(ll x,ll y){ return root(x)==root(y); } bool unite(ll x,ll y){ ll rx=root(x),ry=root(y); if(rx==ry) return 0; if(rk[rx]>e(n); vll dis(n+50,MAX); pqgq;q.push({0ll,start}); dis[start]=0; while(q.em^1){ auto [d,now]=q.top();q.pop(); if(dis[now]>cost){//O((n+m)log(n)) vll dis(n+5,MAX); pqgq;q.push({0ll,start}); dis[start]=0; while(q.em^1){ auto [d,now]=q.top();q.pop(); if(dis[now]np) ret[i-np-1]=Z[i]; R--; }else{ j= i-L; if (Z[j]np) ret[i-np-1]=Z[i]; } } //ff("z"); ou(Z); re ret; } // 2^10 = 1024 //vll dy={-1,-1,-1,0,0,1,1,1},dx={-1,0,1,-1,1,-1,0,1}; /* O(2*10^8) 9*10^18 1LL<<62 4*10^18 ~~(v.be,v.be+n,x); not include v.be+n set.lower_bound(x); ->. *++~ ! /%* +- << < == & && +=?: */ // 12345678901234567890 //vll dy={-1,0,0,1},dx={0,-1,1,0}; ll mod = 1000000007; const ll INF = mod * mod; typedef pairP; #define per(i,n) for(int i=n-1;i>=0;i--) #define Rep(i,sta,n) for(int i=sta;i=1;i--) #define Rep1(i,sta,n) for(int i=sta;i<=n;i++) ll mod_pow(ll x, ll n, ll m = mod) { if (n < 0) { ll res = mod_pow(x, -n, m); return mod_pow(res, m - 2, m); } if (abs(x) >= m)x %= m; if (x < 0)x += m; //if (x == 0)return 0; ll res = 1; while (n) { if (n & 1)res = res * x % m; x = x * x % m; n >>= 1; } return res; } //mod should be <2^31 struct mint { int n; mint() :n(0) { ; } mint(ll m) { if (m < 0 || mod <= m) { m %= mod; if (m < 0)m += mod; } n = m; } operator int() { return n; } }; bool operator==(mint a, mint b) { return a.n == b.n; } bool operator<(mint a, mint b) { return a.n < b.n; } mint operator+=(mint& a, mint b) { a.n += b.n; if (a.n >= mod)a.n -= (int)mod; return a; } mint operator-=(mint& a, mint b) { a.n -= b.n; if (a.n < 0)a.n += (int)mod; return a; } mint operator*=(mint& a, mint b) { a.n = ((ll)a.n * b.n) % mod; return a; } mint operator+(mint a, mint b) { return a += b; } mint operator-(mint a, mint b) { return a -= b; } mint operator*(mint a, mint b) { return a *= b; } mint operator^(mint a, ll n) { if (n == 0)return mint(1); mint res = (a * a) ^ (n / 2); if (n % 2)res = res * a; return res; } ll inv(ll a, ll p) { return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p); } mint operator/(mint a, mint b) { return a * mint(inv(b, mod)); } mint operator/=(mint& a, mint b) { a = a / b; return a; } bool operator==(mint a, ll b) {re a==mint(b);} bool operator<(mint a, ll b) {re a> (istream &is,pnt &r){is>>r.x>>r.y;return is;} //ostream &operator << (ostream &os,pnt &r){os<> (istream &is, mint &x) { ll m; is >> m; if (m < 0 || mod <= m) { m %= mod; if (m < 0)m += mod; } x.n = m; return is; } ostream &operator << (ostream &os, mint &i) { os << i.n; return os; } const int max_n = 1; mint fact[max_n], factinv[max_n]; void init_f() { fact[0] = mint(1); for (int i = 0; i < max_n - 1; i++) { fact[i + 1] = fact[i] * mint(i + 1); } factinv[max_n - 1] = mint(1) / fact[max_n - 1]; for (int i = max_n - 2; i >= 0; i--) { factinv[i] = factinv[i + 1] * mint(i + 1); } } mint comb(int a, int b) { if (a < 0 || b < 0 || a < b)return 0; return fact[a] * factinv[b] * factinv[a - b]; } mint combP(int a, int b) { if (a < 0 || b < 0 || a < b)return 0; return fact[a] * factinv[a - b]; } ll gcd(ll a, ll b) { a = abs(a); b = abs(b); if (a < b)swap(a, b); while (b) { ll r = a % b; a = b; b = r; } return a; } /* SegTreeLazy(n,fx,fa,fm,ex,em): モノイド(集合X, 二項演算fx,fa,fm, 単位元ex,em)についてサイズnで構築 set(int i, X x), build(): i番目の要素をxにセット。まとめてセグ木を構築する。O(n) update(i,x): i 番目の要素を x に更新。O(log(n)) query(a,b): [a,b) 全てにfxを作用させた値を取得。O(log(n)) */ template struct SegTreeLazy { using FX = function; using FAX = function; using FA = function; int n; FX opx; FAX opax; FA opa; const X ex; const A ea; vector dat; vector lazy; SegTreeLazy(int n_, FX opx_, X ex_, FAX opax_, FA opa_, A ea_) : n(), opx(opx_), opax(opax_), opa(opa_), ex(ex_), ea(ea_), dat(n_ * 4, ex), lazy(n_ * 4, ea) { int x = 1; while (n_ > x) x *= 2; n = x; } void set(int i, X x) { dat[i + n - 1] = x; } void build() { for (int k = n - 2; k >= 0; k--) dat[k] = opx(dat[2 * k + 1], dat[2 * k + 2]); } /* lazy eval */ void eval(int k) { if (lazy[k] == ea) return; // 更新するものが無ければ終了 if (k < n - 1) { // 葉でなければ子に伝搬 lazy[k * 2 + 1] = opa(lazy[k * 2 + 1], lazy[k]); lazy[k * 2 + 2] = opa(lazy[k * 2 + 2], lazy[k]); } // 自身を更新 dat[k] = opax(lazy[k],dat[k]); lazy[k] = ea; } void update(int a, int b, A x, int k, int l, int r) { eval(k); if (a <= l && r <= b) { // 完全に内側の時 lazy[k] = opa(lazy[k], x); eval(k); } else if (a < r && l < b) { // 一部区間が被る時 update(a, b, x, k * 2 + 1, l, (l + r) / 2); // 左の子 update(a, b, x, k * 2 + 2, (l + r) / 2, r); // 右の子 dat[k] = opx(dat[k * 2 + 1], dat[k * 2 + 2]); } } void update(int a, int b, A x) { update(a, b, x, 0, 0, n); } X query_sub(int a, int b, int k, int l, int r) { eval(k); if (r <= a || b <= l) { // 完全に外側の時 return ex; } else if (a <= l && r <= b) { // 完全に内側の時 return dat[k]; } else { // 一部区間が被る時 X vl = query_sub(a, b, k * 2 + 1, l, (l + r) / 2); X vr = query_sub(a, b, k * 2 + 2, (l + r) / 2, r); return opx(vl, vr); } } X query(int a, int b) { return query_sub(a, b, 0, 0, n); } }; using X=mint; struct S{ //a*x+b; mint a; mint b; S(mint _a=mint(1),mint _b=mint(0)):a(_a),b(_b){;} }; bool operator==(S a, S b) {re a.a==b.a && a.b==b.b;} using A=S; X opx(X x1,X x2) { return x1+x2; } X ex=0; X opax(A a,X x) { return a.a*x+a.b; } A opa(A a1,A a2) { A a=a1; a.a*=a2.a; a.b*=a2.a; a.b+=a2.b; return a; } A ea ; //SegTreeLazy sg(2*n,opx,ex,opax,opa,ea); struct HLD { int n; vector siz, top, dep, parent, in, out, seq; vector> adj; int cur; HLD() {} HLD(int n) { init(n); } void init(int n) {//初期化 this->n = n; siz.resize(n);//部分木のサイズ top.resize(n);//列の先頭 dep.resize(n);//深さ parent.resize(n);//親 in.resize(n); //新しい番号 out.resize(n);//部分木の最後の番号+1 seq.resize(n);//order iの頂点はseq[i] cur = 0; adj.assign(n, {});//隣接リスト } void add(int u, int v) {//辺を追加 adj[u].push_back(v); adj[v].push_back(u); } void work(int root = 0) {//ビルド top[root] = root; dep[root] = 0; parent[root] = -1; dfs1(root); dfs2(root); } void dfs1(int u) { if (parent[u] != -1) { adj[u].erase(find(adj[u].begin(), adj[u].end(), parent[u])); //親を隣接リストから消す } siz[u] = 1; for (auto &v : adj[u]) { parent[v] = u; dep[v] = dep[u] + 1; dfs1(v); siz[u] += siz[v]; //adj[u][0]をheavyになるようにする if (siz[v] > siz[adj[u][0]]) { swap(v, adj[u][0]); } } } void dfs2(int u) { in[u] = cur++;//新しい番号を割り振る seq[in[u]] = u;//order in[u]の頂点はu for (auto v : adj[u]) { top[v] = v == adj[u][0] ? top[u] : v; dfs2(v); } out[u] = cur; } int lca(int u, int v) { while (top[u] != top[v]) {//同じ列でない間 if (dep[top[u]] > dep[top[v]]) {//深い方から上る u = parent[top[u]]; } else { v = parent[top[v]]; } } return dep[u] < dep[v] ? u : v; } int dist(int u, int v) { return dep[u] + dep[v] - 2 * dep[lca(u, v)]; } int jump(int u, int k) { if (dep[u] < k) { return -1; } int d = dep[u] - k; while (dep[top[u]] > d) { u = parent[top[u]]; } return seq[in[u] - dep[u] + d]; } bool isAncester(int u, int v) { return in[u] <= in[v] && in[v] < out[u]; } int rootedChild(int u, int v) { if (u == v) { return u; } if (!isAncester(u, v)) { return parent[u]; } auto it = std::upper_bound(adj[u].begin(), adj[u].end(), v, [&](int x, int y) { return in[x] < in[y]; }) - 1; return *it; } int rootedSize(int u, int v) { if (u == v) { return n; } if (!isAncester(v, u)) { return siz[v]; } return n - siz[rootedChild(v, u)]; } int rootedLca(int a, int b, int c) { return lca(a, b) ^ lca(b, c) ^ lca(c, a); } }; struct SegTree{ ll n=1;vll v; SegTree(ll _n){ while(n<_n) n*=2; v.resize(n*2,0ll); } ll op(ll a,ll b){ re a+b; } void update(ll pos,ll val){ pos+=n-1; v[pos]=op(v[pos],val); //v[pos]=val; while(pos){ pos=(pos-1)/2; v[pos]=op(v[pos],val); } } ll ran(ll l,ll r){ re sub(l,r,0ll,0ll ,n-1); } ll sub(ll l,ll r,ll nowl,ll now,ll nowr){ if(nowr> v(m+5,vec(2)); i(n) { ge(ll,p); ge(ch,c); v[i%(m)][c=='B']+=p; } vll dp(a+3); //aの残り,bの残り for(ll rem=m;rem>0;--rem) { vll tmp(a+3); for(ll ra=0,rb=min(b,rem);ra<=a&&ra<=rem;++ra,--rb) { if(ra>0) { chmax(tmp[ra-1],dp[ra]+v[rem-1][0]); } if(rb>=0) { chmax(tmp[ra],dp[ra]+v[rem-1][1]); } } swap(tmp,dp); } ff(dp[0]); }