Problem:
タイピング大会 (Typing Contest)
問題文
JOIG 国では JOIG 語が使用されており，JOIG 語では文字
A
,
B
,
C
,
D
,
E
,
F
,
G
,
H
,
I
,
J
,
K
,
L
,
M
,
N
,
O
の
15
種類の文字が用いられる．
来月 JOIG 国で開催されるタイピング大会では，JOIG 語で用いられる
15
種類の文字からなる長さ
N
の文字列
S
を入力するのにかかる時間を競う．この大会では，参加者は以下の条件でタイピングを行う．
参加者は，
1
本の指を使ってタイピングをする．
参加者は，
15
種類の文字のキー
1
つずつを
1
列に並べた，左右に細長いキーボードを使用する．なお，どの位置にどの文字のキーを配置するかは，各参加者が自由に決めることができる．
参加者は，文字列
S
の
1, 2, …, N
文字目のキーをこの順に打つことによって文字列
S
を入力する．
この大会には
Q
人が参加する予定である．参加者によってタイピングの能力は様々である．
i
番目 (
1 ≦ i ≦ Q
) の参加者は，タイピングに際して以下のような時間がかかる．
指の真下にあるキーを
1
回打つのに
A
i
ミリ秒かかる．
指を
1
つ左のキーの上に移動させるのに
L
i
ミリ秒かかる．
指を
1
つ右のキーの上に移動させるのに
R
i
ミリ秒かかる．
文字列
S
および各参加者の情報が与えられるので，各参加者に対して，文字列
S
の最初の文字を打ち始めてから最後の文字を打ち終わるまでに最短何ミリ秒かかるかを求めるプログラムを作成せよ．
制約
1 ≦ N ≦ 1 000 000
．
S
は長さ
N
の文字列である．
S
の各文字は
A
,
B
,
C
,
D
,
E
,
F
,
G
,
H
,
I
,
J
,
K
,
L
,
M
,
N
,
O
のいずれかである．
1 ≦ Q ≦ 150 000
．
1 ≦ A
i
≦ 10
11
(
1 ≦ i ≦ Q
)．
1 ≦ L
i
≦ 10
11
(
1 ≦ i ≦ Q
)．
1 ≦ R
i
≦ 10
11
(
1 ≦ i ≦ Q
)．
N, Q, A
i
, L
i
, R
i
は整数である．
入力
入力は以下の形式で与えられる．
N
S
Q
A
1
L
1
R
1
A
2
L
2
R
2
:
A
Q
L
Q
R
Q
出力
Q
行出力せよ．
i
行目 (
1 ≦ i ≦ Q
) には，参加者
i
が文字列
S
の最初の文字を打ち始めてから最後の文字を打ち終わるまでに最短何ミリ秒かかるかを出力せよ．
入出力例
入力例 1
6
ABAABB
1
100 150 210
出力例 1
1110
例えば，キーボードの配列を左から順に
ONMLKJIHGFEDCBA
とすることを考える．このとき，以下の表のような動作を行うことで，
1110
ミリ秒で文字列
ABAABB
を入力できる．
手順
動作
指の真下にあるキー
時間（ミリ秒）
1
A のキーを打つ
A
100
2
指を
1
つ左のキーの上に移動させる
A → B
150
3
B のキーを打つ
B
100
4
指を
1
つ右のキーの上に移動させる
B → A
210
5
A のキーを打つ
A
100
6
A のキーを打つ
A
100
7
指を
1
つ左のキーの上に移動させる
A → B
150
8
B のキーを打つ
B
100
9
B のキーを打つ
B
100
上に挙げたキーボードの配列以外にも，文字列
ABAABB
を同じ時間で入力できるものはあるが，より短い時間で入力することはできない．よって
1110
を出力する．
入力例 2
6
CBACAB
1
150 240 220
出力例 2
2260
例えば，キーボードの配列を左から順に
CABDEFGHIJKLMNO
とすることを考える．このとき，以下の表のような動作を行うことで，
2260
ミリ秒で文字列
CBACAB
を入力できる．
手順
動作
指の真下にあるキー
時間（ミリ秒）
1
C のキーを打つ
C
150
2
指を
1
つ右のキーの上に移動させる
C → A
220
3
指を
1
つ右のキーの上に移動させる
A → B
220
4
B のキーを打つ
B
150
5
指を
1
つ左のキーの上に移動させる
B → A
240
6
A のキーを打つ
A
150
7
指を
1
つ左のキーの上に移動させる
A → C
240
8
C のキーを打つ
C
150
9
指を
1
つ右のキーの上に移動させる
C → A
220
10
A のキーを打つ
A
150
11
指を
1
つ右のキーの上に移動させる
A → B
220
12
B のキーを打つ
B
150
上に挙げたキーボードの配列以外でも，文字列
CBACAB
を同じ時間で入力できるものはあるが，より短い時間で入力することはできない．よって
2260
を出力する．
入力例 3
20
AAAAAAAAAAAAAAAAAAAA
1
230000000 80000000 80000000
出力例 3
4600000000
A
を
20
回打つことになるので，キーボードの配列にかかわらず，入力し終わるまでに最短で
230000000 × 20 = 4600000000
ミリ秒かかる．よって
4600000000
を出力する．
入力例 4
7
EACHBAG
5
130 104 162
107 219 45
144 168 157
213 79 257
100000000000 100000000000 100000000000
出力例 4
2078
1766
2465
2894
1600000000000
入力例 5
19
JOIGCODINGCHALLENGE
5
1 1 1
100 200 200
225 111 111
123456789 987654321 987654321
31415926535 27182818284 27182818284
出力例 5
48
7700
7494
30987654300
1385204334401
情報オリンピック日本委員会
作 『日本情報オリンピック第3回女性部門 本選 競技課題』

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define sz(A) ((ll)A.size())
#define ALL(A) A.begin(),A.end()
int main(){
    int N;cin>>N;
    string S;cin>>S;
    vvi A(15,vi(15));
    REP(i,N-1)A[S[i]-'A'][S[i+1]-'A']++;
    vvi X(15,vi(15,1e18));
    vvi pre(1<<15,vi(15));
    REP(i,1<<15)REP(j,15){
        ll c=__builtin_popcount(i);
        REP(k,15)if(k!=j){
            if((i>>k)%2)pre[i][j]+=c*(A[j][k]+A[k][j]);
            else pre[i][j]-=c*(A[j][k]+A[k][j]);
        }
    }
    REP(i,15)REP(j,15)if((S[0]==S[N-1])^(i!=j)){
        int s=S[0]-'A',t=S[N-1]-'A';
        vi DP(1<<15,1e18);
        DP[0]=0;
        REP(k,1<<15){
            ll c=__builtin_popcount(k);
            if(c==i){
                if((k>>s)%2)continue;
                DP[k+(1<<s)]=min(DP[k+(1<<s)],DP[k]+pre[k][s]);
            }
            else if(c==j){
                if((k>>t)%2)continue;
                DP[k+(1<<t)]=min(DP[k+(1<<t)],DP[k]+pre[k][t]);
            }
            else{
                REP(l,15)if((k>>l)%2==0)DP[k+(1<<l)]=min(DP[k+(1<<l)],DP[k]+pre[k][l]);
            }
        }
        X[i][j]=DP.back();
    }
    int Q;cin>>Q;
    while(Q--){
        ll a,l,r;cin>>a>>l>>r;
        ll ans=1e18;
        REP(i,15)REP(j,15)if(X[i][j]<1e17){
            ans=min(ans,l*((X[i][j]-(j-i))/2)+r*((X[i][j]+(j-i))/2));
        }
        cout<<a*N+ans<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 520
memory_kb: 9180
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001

#define SIZE 1000005
#define MAX 15

struct Info{
    Info(ll arg_L, ll arg_R) {
        L = arg_L;
        R = arg_R;
    }
    bool operator<(const struct Info& arg) const {
        if (L != arg.L) {
            return L < arg.L;
        } else {
            return R < arg.R;
        }
    }
    ll L, R;
};

ll N;
ll POW[MAX+1];
char buf[SIZE];
ll memo[1024*32], A[SIZE];
ll dp[1024*32];
ll table[MAX][MAX];

int popcount(int x) {
    int count = 0;
    while (x) {
        count += x & 1;
        x >>= 1;
    }
    return count;
}

int main() {

    POW[0] = 1;
    for (int i = 1; i <= MAX; i++) {
        POW[i] = POW[i-1]*2;
    }

    scanf("%lld %s", &N, buf);
    for (ll i = 0; i < N; i++) {
        A[i] = buf[i] - 'A';
    }
    for (ll i = 0; i < N-1; i++) {
        table[A[i]][A[i+1]]++; // A[i]の次にA[i+1]を打つ必要がある回数
    }

    // 集合による、左方移動の最小値を前計算
    for (int state = 1; state < POW[MAX]-1; state++) {
        vector<int> P, Q;
        for (int loop = 0; loop < MAX; loop++) {
            if (state & POW[loop]) {
                P.push_back(loop); // 左方に配置済
            } else {
                Q.push_back(loop); // 未配置(右方にある)
            }
        }

        ll tmp = 0;

        for (size_t a = 0; a < P.size(); a++) {
            int to = P[a];
            for (size_t b = 0; b < Q.size(); b++) {
                int from = Q[b];
                tmp += table[from][to]; // 左方への動きを数える
            }
        }
        memo[state] = tmp;
    }

    vector<Info> vec;

    ll head = A[0], tail = A[N-1];

    if (head == tail) {
        for (int loc = 0; loc < MAX; loc++) {
            // dp初期化
            for (ll state = 0; state < POW[MAX]; state++) {
                dp[state] = HUGE_NUM;
            }

            dp[0] = 0;

            for (ll state = 0; state < POW[MAX]; state++) {
                int p_count = popcount(state);
                if (p_count == loc) { // 次はhead
                    ll next_state = state | POW[head];
                    ll add = memo[next_state];
                    chmin(dp[next_state], dp[state] + add);
                } else {
                    for (int next = 0; next < MAX; next++) {
                        if (next == head) continue;
                        if (state & POW[next]) continue;

                        ll next_state = state | POW[next];
                        ll add = memo[next_state];
                        chmin(dp[next_state], dp[state] + add);
                    }
                }
            }
            vec.push_back(Info(dp[POW[MAX]-1], dp[POW[MAX]-1])); // 左右の合計移動回数は同じ
        }
    } else {
        for (int i = 0; i < MAX; i++) { // headの位置
            for (int k = 0; k < MAX; k++) { // tailの位置
                if (k == i) continue;

                // dp初期化
                for (ll state = 0; state < POW[MAX]; state++) {
                    dp[state] = HUGE_NUM;
                }
                dp[0] = 0;

                for (ll state = 0; state < POW[MAX]; state++) {
                    int p_count = popcount(state);
                    if (p_count == i) {
                        ll next_state = state | POW[head];
                        ll add = memo[next_state];
                        chmin(dp[next_state], dp[state] + add);
                    } else if (p_count == k) {
                        ll next_state = state | POW[tail];
                        ll add = memo[next_state];
                        chmin(dp[next_state], dp[state] + add);
                    } else {
                        for (int next = 0; next < MAX; next++) {
                            if (next == head || next == tail) continue;
                            if (state & POW[next]) continue;

                            ll next_state = state | POW[next];
                            ll add = memo[next_state];
                            chmin(dp[next_state], dp[state] + add);
                        }
                    }
                }

                ll toL = dp[POW[MAX]-1], toR = toL + (k - i);
                vec.push_back(Info(toL, toR));
            }
        }
    }

    sort(vec.begin(), vec.end());
    ll mini = HUGE_NUM;

    vector<Info> V;
    for (size_t i = 0; i < vec.size(); i++) {
        if (vec[i].R < mini) {
            mini = vec[i].R;
            V.push_back(vec[i]); // Lの昇順に見ていくので、Rは過去最小値のものだけ採用
        }
    }

    int numQ;
    scanf("%d", &numQ);

    ll valA, valL, valR;

    for (int loop = 0; loop < numQ; loop++) {
        scanf("%lld %lld %lld", &valA, &valL, &valR);

        int L = 0, R = V.size() - 1;

        ll calcL = valL * V[L].L + valR * V[L].R + valA * N;
        ll calcR = valL * V[R].L + valR * V[R].R + valA * N;

        ll ans = min(calcL, calcR);

        int pre1 = -1;
        int pre2 = -1;

        for (int loop = 0; loop < 100; loop++) {
            int mid1 = (2 * L + R) / 3;
            int mid2 = (L + 2 * R) / 3;

            if (mid1 == pre1 && mid2 == pre2) {
                if (mid2 - mid1 == 2) {
                    ll work = valL * V[mid2 - 1].L + valR * V[mid2 - 1].R + valA * N;
                    chmin(ans, work);
                }
                break;
            }

            ll val1 = valL * V[mid1].L + valR * V[mid1].R + valA * N;
            ll val2 = valL * V[mid2].L + valR * V[mid2].R + valA * N;

            chmin(ans, min(val1, val2));

            if (val1 > val2) {
                L = mid1;
            } else {
                R = mid2;
            }
            pre1 = mid1;
            pre2 = mid2;
        }

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

    return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 12900
final_rank: 5

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, q;
    string s;
    cin >> n >> s >> q;
    const int M = 15;
    vector<vector<int>> cnt(M, vector<int>(M));
    for (int i = 0; i + 1 < n; i++) {
        cnt[s[i] - 'A'][s[i + 1] - 'A'] += 1;
    }
    int S = s[0] - 'A', T = s.back() - 'A';
    const int inf = 2e9;
    const int K = 14;
    vector<int> cal(K * 2 + 1, inf);

    vector<int> popcount(1 << M);
    for (int i = 0; i < (1 << M); i++) {
        popcount[i] = __builtin_popcount(i);
    }
    vector<int> pre(1 << M);
    for (int i = 0; i < (1 << M); i++) {
        for (int j = 0; j < M; j++) {
            if ((1 << j) & i) continue;
            for (int k = 0; k < M; k++) {
                if ((1 << k) & i) pre[i] += cnt[j][k];
            }
        }
    }

    // (Tの位置)-(Sの位置) = i
    for (int i = -K; i <= K; i++) {
        if ((S == T) ^ (i == 0)) continue;
        for (int a = 0; a < M; a++) {
            int b = a + i;
            if (b < 0 or M <= b) continue;

            vector<int> dp((1 << M), inf);
            dp[0] = 0;
            for (int j = 0; j < (1 << M); j++) {
                for (int k = 0; k < M; k++) {
                    if ((1 << k) & j) continue;
                    if (k == S and popcount[j] != a) continue;
                    if (k == T and popcount[j] != b) continue;
                    int nxt = j + (1 << k);
                    dp[nxt] = min(dp[nxt], dp[j] + pre[nxt]);
                }
            }

            cal[i + K] = min(cal[i + K], dp.back());
        }
    }

    while (q--) {
        ll a, l, r;
        cin >> a >> l >> r;
        ll res = (ll)inf * (ll)inf;
        for (int i = -K; i <= K; i++) {
            ll cntL = cal[i + K];
            if (cntL == inf) continue;
            ll cntR = cntL + i;
            res = min(res, cntL * l + cntR * r);
        }
        res += a * n;
        cout << res << "\n";
    }
}
accuracy: 1
time_ms: 380
memory_kb: 4428
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
#define all(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
template<class T>
bool chmax(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}
template<class T>
bool chmin(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

int main() {

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

    ll N, Q;
    string S;
    cin >> N >> S >> Q;
    ll CN = 15;
    vvll P(CN, vll(CN, 0));
    rep(i, N - 1) {
        P[S[i] - 'A'][S[i + 1] - 'A']++;
    }

    vll ML(1 << CN, 0), MR(1 << CN, 0);
    rep(bit, 1 << CN) {
        rep(i, CN)rep(j, CN) {
            if (bit & (1 << i)) {
                if (!(bit & (1 << j))) {
                    MR[bit] += P[i][j];
                    ML[bit] += P[j][i];
                }
            }
        }
    }
    map<ll, ll> RminusL;
    rep(i, CN)rep(j, CN) {//S[0]がi番目,S[N-1]がj番目 
        if (S[0] == S[N - 1] && i != j)continue;
        if (S[0] != S[N - 1] && i == j)continue;
        vll DP(1 << CN, 1e18);
        DP[0] = 0;
        rep(bit, 1 << CN) {
            ll cnt = 0;
            rep(k, CN)if (bit & (1 << k))cnt++;

            rep(k, CN) {
                if (cnt == i && k != S[0] - 'A')continue;
                if (cnt == j && k != S[N - 1] - 'A')continue;
                if (bit & (1 << k))continue;
                ll nbit = bit + (1 << k);
                ll cost = MR[nbit];
                chmin(DP[bit + (1 << k)], DP[bit] + cost);
            }
        }
        if(!RminusL.count(i-j))
        RminusL[i - j] = DP[(1 << CN) - 1];

        chmin(RminusL[i - j], DP[(1 << CN) - 1]);
    }

    rep(q, Q) {
        ll A, L, R;
        cin >> A >> L >> R;
        ll an = A * N;
        ll bn = 1e18;
        for (auto m : RminusL) {
            ll RN = m.second;
            ll LN = RN + m.first;
            chmin(bn, R * RN + L * LN);
        }
        cout << an + bn << endl;
    }


}
accuracy: 1
time_ms: 540
memory_kb: 4920
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 1000005
#define MAX 15

struct Info{
	Info(ll arg_L,ll arg_R){
		L = arg_L;
		R = arg_R;
	}
	bool operator<(const struct Info& arg) const{
		if(L != arg.L){

			return L < arg.L;
		}else{

			return R < arg.R;
		}
	}
	ll L,R;
};

ll N;
ll POW[MAX+1];
char buf[SIZE];
ll memo[1024*32],A[SIZE];
ll dp[1024*32];
ll table[MAX][MAX];


int main(){

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

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

	scanf("%lld %s",&N,buf);
	for(ll i = 0; i < N; i++){

		A[i] = buf[i]-'A';
	}
	for(ll i = 0; i < N-1; i++){

		table[A[i]][A[i+1]]++; //A[i]の次にA[i+1]を打つ必要がある回数
	}

	//集合による、左方移動の最小値を前計算
	for(int state = 1; state < POW[MAX]-1; state++){
		vector<int> P,Q;
		for(int loop = 0; loop < MAX; loop++){
			if(state&POW[loop]){

				P.push_back(loop); //左方に配置済

			}else{

				Q.push_back(loop); //未配置(右方にある)
			}
		}

		ll tmp = 0;

		for(int a = 0; a < P.size(); a++){
			int  to = P[a];

			for(int b = 0; b < Q.size(); b++){
				int from = Q[b];
				tmp += table[from][to]; //左方への動きを数える
			}
		}
		memo[state] = tmp;
	}

	vector<Info> vec;

	ll head = A[0],tail = A[N-1];

	if(head == tail){

		for(int loc = 0; loc < MAX; loc++){

			//dp初期化
			for(ll state = 0; state < POW[MAX]; state++){
				dp[state] = HUGE_NUM;
			}

			dp[0] = 0;

			for(ll state = 0; state < POW[MAX]; state++){
				int p_count = __builtin_popcount(state);
				if(p_count == loc){ //■次はhead

					ll next_state = state|POW[head];
					ll add = memo[next_state];
					chmin(dp[next_state],dp[state]+add);

				}else{

					for(int next = 0; next < MAX; next++){
						if(next == head)continue;
						if(state&POW[next])continue;

						ll next_state = state|POW[next];
						ll add = memo[next_state];
						chmin(dp[next_state],dp[state]+add);
					}
				}
			}
			vec.push_back(Info(dp[POW[MAX]-1],dp[POW[MAX]-1])); //左右の合計移動回数は同じ
		}


	}else{

		for(int i = 0; i < MAX; i++){ //headの位置
			for(int k = 0; k < MAX; k++){ //tailの位置
				if(k == i)continue;

				//dp初期化
				for(ll state = 0; state < POW[MAX]; state++){
					dp[state] = HUGE_NUM;
				}
				dp[0] = 0;

				for(ll state = 0; state < POW[MAX]; state++){
					int p_count = __builtin_popcount(state);
					if(p_count == i){

						ll next_state = state|POW[head];
						ll add = memo[next_state];
						chmin(dp[next_state],dp[state]+add);

					}else if(p_count == k){

						ll next_state = state|POW[tail];
						ll add = memo[next_state];
						chmin(dp[next_state],dp[state]+add);

					}else{

						for(int next = 0; next < MAX; next++){
							if(next == head || next == tail)continue;
							if(state&POW[next])continue;

							ll next_state = state|POW[next];
							ll add = memo[next_state];
							chmin(dp[next_state],dp[state]+add);
						}
					}
				}

				ll toL = dp[POW[MAX]-1],toR = toL + (k-i);
				vec.push_back(Info(toL,toR));
			}
		}
	}

	sort(vec.begin(),vec.end());
	ll mini = HUGE_NUM;

	vector<Info> V;
	for(int i = 0; i < vec.size(); i++){
		if(vec[i].R < mini){

			mini = vec[i].R;
			V.push_back(vec[i]); //Lの昇順に見ていくので、Rは過去最小値のものだけ採用
		}
	}

	int numQ;
	scanf("%d",&numQ);

	ll valA,valL,valR;

	for(int loop = 0; loop < numQ; loop++){

		scanf("%lld %lld %lld",&valA,&valL,&valR);

		int L = 0,R = V.size()-1;

		ll calcL = valL*V[L].L + valR*V[L].R + valA*N;
		ll calcR = valL*V[R].L + valR*V[R].R + valA*N;

		ll ans = min(calcL,calcR);

		int pre1 = -1;
		int pre2 = -1;

		for(int loop = 0; loop < 100; loop++){

			int mid1 = (2*L+R)/3;
			int mid2 = (L+2*R)/3;

			if(mid1 == pre1 && mid2 == pre2){
				if(mid2-mid1 == 2){

					ll work = valL*V[mid2-1].L + valR*V[mid2-1].R + valA*N;
					chmin(ans,work);
				}
				break;
			}

			ll val1 = valL*V[mid1].L + valR*V[mid1].R + valA*N;
			ll val2 = valL*V[mid2].L + valR*V[mid2].R + valA*N;

			chmin(ans,min(val1,val2));

			if(val1 > val2){

				L = mid1;
			}else{

				R = mid2;
			}
			pre1 = mid1;
			pre2 = mid2;
		}

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

	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 12520
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 1000005
#define MAX 15

struct Info{
	Info(ll arg_L,ll arg_R){
		L = arg_L;
		R = arg_R;
	}
	bool operator<(const struct Info& arg) const{
		if(L != arg.L){

			return L < arg.L;
		}else{

			return R < arg.R;
		}
	}
	ll L,R;
};

ll N;
ll POW[MAX+1];
char buf[SIZE];
ll memo[1024*32],A[SIZE];
ll dp[1024*32];
ll table[MAX][MAX];


int main(){

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

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

	scanf("%lld %s",&N,buf);
	for(ll i = 0; i < N; i++){

		A[i] = buf[i]-'A';
	}
	for(ll i = 0; i < N-1; i++){

		table[A[i]][A[i+1]]++; //A[i]→A[i+1]が隣接している回数
	}

	for(int state = 1; state < POW[MAX]-1; state++){
		vector<int> P,Q;
		for(int loop = 0; loop < MAX; loop++){
			if(state&POW[loop]){

				P.push_back(loop); //左方に配置済

			}else{

				Q.push_back(loop); //未配置(右方にある)
			}
		}

		ll tmp = 0;

		for(int a = 0; a < P.size(); a++){
			int  to = P[a];

			for(int b = 0; b < Q.size(); b++){
				int from = Q[b];
				tmp += table[from][to]; //左方への動きを数える
			}
		}
		memo[state] = tmp;
	}

	vector<Info> vec;

	ll head = A[0],tail = A[N-1];

	if(head == tail){

		for(int loc = 0; loc < MAX; loc++){

			//dp初期化
			for(ll state = 0; state < POW[MAX]; state++){
				dp[state] = HUGE_NUM;
			}

			dp[0] = 0;

			for(ll state = 0; state < POW[MAX]; state++){
				int p_count = __builtin_popcount(state);
				if(p_count == loc){ //■次はhead

					ll next_state = state|POW[head];
					ll add = memo[next_state];
					chmin(dp[next_state],dp[state]+add);

				}else{

					for(int next = 0; next < MAX; next++){
						if(next == head)continue;
						if(state&POW[next])continue;

						ll next_state = state|POW[next];
						ll add = memo[next_state];
						chmin(dp[next_state],dp[state]+add);
					}
				}
			}
			vec.push_back(Info(dp[POW[MAX]-1],dp[POW[MAX]-1])); //左右の合計移動回数は同じ
		}


	}else{

		for(int i = 0; i < MAX; i++){ //headの位置
			for(int k = 0; k < MAX; k++){ //tailの位置
				if(k == i)continue;

				//dp初期化
				for(ll state = 0; state < POW[MAX]; state++){
					dp[state] = HUGE_NUM;
				}
				dp[0] = 0;

				for(ll state = 0; state < POW[MAX]; state++){
					int p_count = __builtin_popcount(state);
					if(p_count == i){

						ll next_state = state|POW[head];
						ll add = memo[next_state];
						chmin(dp[next_state],dp[state]+add);

					}else if(p_count == k){

						ll next_state = state|POW[tail];
						ll add = memo[next_state];
						chmin(dp[next_state],dp[state]+add);

					}else{

						for(int next = 0; next < MAX; next++){
							if(next == head || next == tail)continue;
							if(state&POW[next])continue;

							ll next_state = state|POW[next];
							ll add = memo[next_state];
							chmin(dp[next_state],dp[state]+add);
						}
					}
				}

				ll toL = dp[POW[MAX]-1],toR = toL + k-i;
				vec.push_back(Info(toL,toR));
			}
		}
	}

	sort(vec.begin(),vec.end());
	ll mini = HUGE_NUM;

	vector<Info> V;
	for(int i = 0; i < vec.size(); i++){
		if(vec[i].R < mini){

			mini = vec[i].R;
			V.push_back(vec[i]); //Lの昇順に見ていくので、Rは過去最小値のものだけ採用
		}
	}

	/*for(int i = 0; i < V.size(); i++){

		printf("L:%lld R:%lld\n",V[i].L,V[i].R);
	}*/

	int numQ;
	scanf("%d",&numQ);

	ll valA,valL,valR;

	for(int loop = 0; loop < numQ; loop++){

		scanf("%lld %lld %lld",&valA,&valL,&valR);

		int L = 0,R = V.size()-1;

		ll calcL = valL*V[L].L + valR*V[L].R + valA*N;
		ll calcR = valL*V[R].L + valR*V[R].R + valA*N;

		ll ans = min(calcL,calcR);

		int pre1 = -1;
		int pre2 = -1;

		for(int loop = 0; loop < 100; loop++){

			int mid1 = (2*L+R)/3;
			int mid2 = (L+2*R)/3;

			if(mid1 == pre1 && mid2 == pre2){
				if(mid2-mid1 >= 2){

					ll work = valL*V[mid2-1].L + valR*V[mid2-1].R + valA*N;
					chmin(ans,work);
				}
				break;
			}

			//printf("mid1:%d mid2:%d\n",mid1,mid2);

			ll val1 = valL*V[mid1].L + valR*V[mid1].R + valA*N;
			ll val2 = valL*V[mid2].L + valR*V[mid2].R + valA*N;

			chmin(ans,min(val1,val2));

			if(val1 > val2){

				L = mid1;
			}else{

				R = mid2;
			}
			pre1 = mid1;
			pre2 = mid2;
		}

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

	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 12532
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 1000005
#define MAX 15

struct Info{
	Info(ll arg_L,ll arg_R){
		L = arg_L;
		R = arg_R;
	}
	bool operator<(const struct Info& arg) const{
		if(L != arg.L){

			return L < arg.L;
		}else{

			return R < arg.R;
		}
	}
	ll L,R;
};

ll N;
ll POW[MAX+1];
char buf[SIZE];
ll memo[1024*32],A[SIZE];
ll dp[1024*32];
ll table[MAX][MAX];


int main(){

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

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

	scanf("%lld %s",&N,buf);
	for(ll i = 0; i < N; i++){

		A[i] = buf[i]-'A';
	}
	for(ll i = 0; i < N-1; i++){

		table[A[i]][A[i+1]]++; //A[i]→A[i+1]が隣接している回数
	}

	for(int state = 1; state < POW[MAX]-1; state++){
		vector<int> P,Q;
		for(int loop = 0; loop < MAX; loop++){
			if(state&POW[loop]){

				P.push_back(loop); //左方に配置済

			}else{

				Q.push_back(loop); //未配置(右方にある)
			}
		}

		ll tmp = 0;

		for(int a = 0; a < P.size(); a++){
			int  to = P[a];

			for(int b = 0; b < Q.size(); b++){
				int from = Q[b];
				tmp += table[from][to]; //左方への動きを数える
			}
		}
		memo[state] = tmp;
	}

	vector<Info> vec;

	ll head = A[0],tail = A[N-1];

	if(head == tail){

		for(int loc = 0; loc < MAX; loc++){

			//dp初期化
			for(ll state = 0; state < POW[MAX]; state++){
				dp[state] = HUGE_NUM;
			}

			dp[0] = 0;

			for(ll state = 0; state < POW[MAX]; state++){
				int p_count = __builtin_popcount(state);
				if(p_count == loc){ //■次はhead

					ll next_state = state|POW[head];
					ll add = memo[next_state];
					chmin(dp[next_state],dp[state]+add);

				}else{

					for(int next = 0; next < MAX; next++){
						if(next == head)continue;
						if(state&POW[next])continue;

						ll next_state = state|POW[next];
						ll add = memo[next_state];
						chmin(dp[next_state],dp[state]+add);
					}
				}
			}
			vec.push_back(Info(dp[POW[MAX]-1],dp[POW[MAX]-1])); //左右の合計移動回数は同じ
		}


	}else{

		for(int i = 0; i < MAX; i++){ //headの位置
			for(int k = 0; k < MAX; k++){ //tailの位置
				if(k == i)continue;

				//dp初期化
				for(ll state = 0; state < POW[MAX]; state++){
					dp[state] = HUGE_NUM;
				}
				dp[0] = 0;

				for(ll state = 0; state < POW[MAX]; state++){
					int p_count = __builtin_popcount(state);
					if(p_count == i){

						ll next_state = state|POW[head];
						ll add = memo[next_state];
						chmin(dp[next_state],dp[state]+add);

					}else if(p_count == k){

						ll next_state = state|POW[tail];
						ll add = memo[next_state];
						chmin(dp[next_state],dp[state]+add);

					}else{

						for(int next = 0; next < MAX; next++){
							if(next == head || next == tail)continue;
							if(state&POW[next])continue;

							ll next_state = state|POW[next];
							ll add = memo[next_state];
							chmin(dp[next_state],dp[state]+add);
						}
					}
				}

				ll toL = dp[POW[MAX]-1],toR = toL + k-i;
				if(toL == 0){
					printf("■■i:%d k;%d\n",i,k);

				}
				vec.push_back(Info(toL,toR));
			}
		}
	}

	sort(vec.begin(),vec.end());
	ll mini = HUGE_NUM;

	vector<Info> V;
	for(int i = 0; i < vec.size(); i++){
		if(vec[i].R < mini){

			mini = vec[i].R;
			V.push_back(vec[i]); //Lの昇順に見ていくので、Rは過去最小値のものだけ採用
		}
	}

	/*for(int i = 0; i < V.size(); i++){

		printf("L:%lld R:%lld\n",V[i].L,V[i].R);
	}*/

	int numQ;
	scanf("%d",&numQ);

	ll valA,valL,valR;

	for(int loop = 0; loop < numQ; loop++){

		scanf("%lld %lld %lld",&valA,&valL,&valR);

		int L = 0,R = V.size()-1;

		ll calcL = valL*V[L].L + valR*V[L].R + valA*N;
		ll calcR = valL*V[R].L + valR*V[R].R + valA*N;

		ll ans = min(calcL,calcR);

		int pre1 = -1;
		int pre2 = -1;

		for(int loop = 0; loop < 100; loop++){

			int mid1 = (2*L+R)/3;
			int mid2 = (L+2*R)/3;

			if(mid1 == pre1 && mid2 == pre2){
				if(mid2-mid1 >= 2){

					ll work = valL*V[mid2-1].L + valR*V[mid2-1].R + valA*N;
					chmin(ans,work);
				}
				break;
			}

			//printf("mid1:%d mid2:%d\n",mid1,mid2);

			ll val1 = valL*V[mid1].L + valR*V[mid1].R + valA*N;
			ll val2 = valL*V[mid2].L + valR*V[mid2].R + valA*N;

			chmin(ans,min(val1,val2));

			if(val1 > val2){

				L = mid1;
			}else{

				R = mid2;
			}
			pre1 = mid1;
			pre2 = mid2;
		}

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

	return 0;
}
accuracy: 0.7692307692307693
time_ms: 290
memory_kb: 12528
final_rank: 10

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

using namespace std;

#define rep(i,n) for(int i=0;i<(n);++i)
#define reps(i,n) for(int i=1;i<=(n);++i)
#define all(x) begin(x),end(x)
#define Fixed fixed << setprecision(12)
#define updiv(a, b) (((a) + (b) - 1) / (b))
using pii = pair<int,int>;
constexpr int INF  = 0x3f3f3f3f;
constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int mod1 = 1e9+7;
constexpr int mod2 = 998244353;

template <class Func>
class FixPoint : Func {
public:
    explicit constexpr FixPoint(Func&& f) noexcept : Func(forward<Func>(f)) {}

    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return Func::operator()(*this, std::forward<Args>(args)...);
    }
};

template <class Func>
static inline constexpr decltype(auto) makeFixPoint(Func&& f) noexcept {
    return FixPoint<Func>{forward<Func>(f)};
}

template<class T, class U> istream& operator>>(istream& is, pair<T, U>& p){ is >> p.first >> p.second; return (is); }
template<class T, class U> ostream& operator<<(ostream& os, pair<T, U>& p){ os << p.first << ' ' << p.second; return (os); }
template<class T> istream& operator>>(istream& is, vector<T>& v){ for (auto &&e : v) is >> e; return (is); }
template<class T> ostream& operator<<(ostream& os, vector<T>& v){ for (auto &&e : v) os << e << ' '; return (os); }

template<class T> inline const T& max(const vector<T> &v) { return *max_element(v.begin(), v.end()); }
template<class T> inline const T& min(const vector<T> &v) { return *min_element(v.begin(), v.end()); }
template <class A, class B> inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }
template <class A, class B> inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }

template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T, vector<T>, greater<T> >;
template <class A, class B> using umap = unordered_map<A, B>;
template <class T> using uset = unordered_set<T>;

template <class T> using Max_Heap = __gnu_pbds::priority_queue<T, less<T>, __gnu_pbds::rc_binomial_heap_tag>;
template <class T> using Min_Heap = __gnu_pbds::priority_queue<T, greater<T>, __gnu_pbds::rc_binomial_heap_tag>;
template <class T> using Set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
template <class K, class V> using Umap = __gnu_pbds::gp_hash_table<K, V>;
template <class T> using Rope = __gnu_cxx::rope<T>;
using Trie = __gnu_pbds::trie<string, __gnu_pbds::null_type, __gnu_pbds::trie_string_access_traits<>, __gnu_pbds::pat_trie_tag, __gnu_pbds::trie_prefix_search_node_update>;

template <class T> void bye(T x){ cout << x << '\n'; exit(0); }

constexpr int dx[] = {1,0,-1,0,1,1,-1,-1,0};
constexpr int dy[] = {0,-1,0,1,1,-1,-1,1,0};

signed main(){
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout.setf(ios_base::fixed);
    cout.precision(12);

    int n, q, m = 15;
    string s;
    cin >> n >> s >> q;

    assert(1 <= n && n <= 1000000);
    assert(s.size() == n);
    assert(all_of(all(s), [](char c) { return 'A' <= c && c <= 'O'; }));
    assert(1 <= q && q <= 150000);

    vector<int> v(n);
    vector<vector<int> > cnt(m, vector<int>(m));

    for (int i = 0; i < n; ++i) {
        v[i] = s[i] - 'A';
    }

    for (int i = 1; i < n; ++i) {
        cnt[v[i - 1]][v[i]]++;
    }

    vector<long long> sum(1 << m);

    for (int mask = 0; mask < 1 << m; ++mask) {
        for (int i = 0; i < m; ++i) {
            if (mask >> i & 1) {
                for (int j = 0; j < m; ++j) {
                    if (~mask >> j & 1) {
                        sum[mask] += cnt[i][j];
                    }
                }
            }
        }
    }

    long long *minv = new long long[2 * m];

    for (int i = 0; i < 2 * m; ++i) minv[i] = LINF;

    minv = minv + m;

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < m; ++j) {
            vector<long long> dp(1 << m, LINF);
            dp[0] = 0;
            for (int mask = 0; mask < 1 << m; ++mask) {
                if (__builtin_popcount(mask) == i) {
                    if (mask >> v[0] & 1) continue;
                    int nxt = mask | 1 << v[0];
                    chmin(dp[nxt], dp[mask] + sum[(1 << m) - 1 & ~nxt]);
                } else if (__builtin_popcount(mask) == j) {
                    if (mask >> v[n - 1] & 1) continue;
                    int nxt = mask | 1 << v[n - 1];
                    chmin(dp[nxt], dp[mask] + sum[(1 << m) - 1 & ~nxt]);
                } else {
                    for (int k = 0; k < m; ++k) {
                        if (k == v[0] || k == v[n - 1]) continue;
                        if (mask >> k & 1) continue;
                        int nxt = mask | 1 << k;
                        chmin(dp[nxt], dp[mask] + sum[(1 << m) - 1 & ~nxt]);
                    }
                }
            }
            chmin(minv[j - i], dp.back());
        }
    }

    for (int i = 0; i < q; ++i) {
        long long a, l, r;
        cin >> a >> l >> r;

        assert(1 <= a && 100000000000);
        assert(1 <= l && 100000000000);
        assert(1 <= r && 100000000000);

        long long res = LINF;

        for (int j = -m + 1; j < m; ++j) {
            if (minv[j] == LINF) continue;
            chmin(res, minv[j] * l + (minv[j] + j) * r);
        }

        cout << res + a * n << '\n';
    }

    return (0);
}
accuracy: 1
time_ms: 350
memory_kb: 8556
final_rank: 2

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

using namespace std;

#define rep(i,n) for(int i=0;i<(n);++i)
#define reps(i,n) for(int i=1;i<=(n);++i)
#define all(x) begin(x),end(x)
#define Fixed fixed << setprecision(12)
#define updiv(a, b) (((a) + (b) - 1) / (b))
using pii = pair<int,int>;
constexpr int INF  = 0x3f3f3f3f;
constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int mod1 = 1e9+7;
constexpr int mod2 = 998244353;

template <class Func>
class FixPoint : Func {
public:
    explicit constexpr FixPoint(Func&& f) noexcept : Func(forward<Func>(f)) {}

    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return Func::operator()(*this, std::forward<Args>(args)...);
    }
};

template <class Func>
static inline constexpr decltype(auto) makeFixPoint(Func&& f) noexcept {
    return FixPoint<Func>{forward<Func>(f)};
}

template<class T, class U> istream& operator>>(istream& is, pair<T, U>& p){ is >> p.first >> p.second; return (is); }
template<class T, class U> ostream& operator<<(ostream& os, pair<T, U>& p){ os << p.first << ' ' << p.second; return (os); }
template<class T> istream& operator>>(istream& is, vector<T>& v){ for (auto &&e : v) is >> e; return (is); }
template<class T> ostream& operator<<(ostream& os, vector<T>& v){ for (auto &&e : v) os << e << ' '; return (os); }

template<class T> inline const T& max(const vector<T> &v) { return *max_element(v.begin(), v.end()); }
template<class T> inline const T& min(const vector<T> &v) { return *min_element(v.begin(), v.end()); }
template <class A, class B> inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }
template <class A, class B> inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }

template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T, vector<T>, greater<T> >;
template <class A, class B> using umap = unordered_map<A, B>;
template <class T> using uset = unordered_set<T>;

template <class T> using Max_Heap = __gnu_pbds::priority_queue<T, less<T>, __gnu_pbds::rc_binomial_heap_tag>;
template <class T> using Min_Heap = __gnu_pbds::priority_queue<T, greater<T>, __gnu_pbds::rc_binomial_heap_tag>;
template <class T> using Set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
template <class K, class V> using Umap = __gnu_pbds::gp_hash_table<K, V>;
template <class T> using Rope = __gnu_cxx::rope<T>;
using Trie = __gnu_pbds::trie<string, __gnu_pbds::null_type, __gnu_pbds::trie_string_access_traits<>, __gnu_pbds::pat_trie_tag, __gnu_pbds::trie_prefix_search_node_update>;

template <class T> void bye(T x){ cout << x << '\n'; exit(0); }

constexpr int dx[] = {1,0,-1,0,1,1,-1,-1,0};
constexpr int dy[] = {0,-1,0,1,1,-1,-1,1,0};

signed main(){
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout.setf(ios_base::fixed);
    cout.precision(12);

    int n, q, m = 15;
    string s;
    cin >> n >> s >> q;

    vector<int> v(n);
    vector<vector<int> > cnt(m, vector<int>(m));

    for (int i = 0; i < n; ++i) {
        v[i] = s[i] - 'A';
    }

    for (int i = 1; i < n; ++i) {
        cnt[v[i - 1]][v[i]]++;
    }

    vector<long long> sum(1 << m);

    for (int mask = 0; mask < 1 << m; ++mask) {
        for (int i = 0; i < m; ++i) {
            if (mask >> i & 1) {
                for (int j = 0; j < m; ++j) {
                    if (~mask >> j & 1) {
                        sum[mask] += cnt[i][j];
                    }
                }
            }
        }
    }

    long long *minv = new long long[2 * m];

    for (int i = 0; i < 2 * m; ++i) minv[i] = LINF;

    minv = minv + m;

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < m; ++j) {
            vector<long long> dp(1 << m, LINF);
            dp[0] = 0;
            for (int mask = 0; mask < 1 << m; ++mask) {
                if (__builtin_popcount(mask) == i) {
                    if (mask >> v[0] & 1) continue;
                    int nxt = mask | 1 << v[0];
                    chmin(dp[nxt], dp[mask] + sum[(1 << m) - 1 & ~nxt]);
                } else if (__builtin_popcount(mask) == j) {
                    if (mask >> v[n - 1] & 1) continue;
                    int nxt = mask | 1 << v[n - 1];
                    chmin(dp[nxt], dp[mask] + sum[(1 << m) - 1 & ~nxt]);
                } else {
                    for (int k = 0; k < m; ++k) {
                        if (k == v[0] || k == v[n - 1]) continue;
                        if (mask >> k & 1) continue;
                        int nxt = mask | 1 << k;
                        chmin(dp[nxt], dp[mask] + sum[(1 << m) - 1 & ~nxt]);
                    }
                }
            }
            chmin(minv[j - i], dp.back());
        }
    }

    for (int i = 0; i < q; ++i) {
        long long a, l, r;
        cin >> a >> l >> r;

        long long res = LINF;

        for (int j = -m + 1; j < m; ++j) {
            if (minv[j] == LINF) continue;
            chmin(res, minv[j] * l + (minv[j] + j) * r);
        }

        cout << res + a * n << '\n';
    }

    return (0);
}
accuracy: 1
time_ms: 310
memory_kb: 8568
final_rank: 1

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

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll n, A, L, R;
    int Q;
    string s;
    cin >> n >> s >> Q;
    vector<vector<ll>> B(15, vector<ll>(15)), dp(1 << 15, vector<ll>(512, INF));
    vector<pair<ll,ll>> C(1 << 15);
    for(int i = 0; i + 1 < n; i++){
        B[s[i] - 'A'][s[i + 1] - 'A']++;
    }
    for(int i = 0; i < (1 << 15); i++){
        R = 0, L = 0;
        for(int j = 0; j < 15; j++){
            for(int k = 0; k < 15; k++){
                if((i >> j & 1) ^ (i >> k & 1)){
                    if(i >> j & 1) R += B[j][k];
                    else L += B[j][k];
                }
            }
        }
        C[i] = make_pair(R, L);
    }
    dp[0][256] = 0;
    for(int i = 0; i < (1 << 15); i++){
        for(int j = 0; j < 512; j++){
            if(dp[i][j] == INF)continue;
            for(int k = 0; k < 15; k++){
                if(i >> k & 1)continue;
                tie(R, L) = C[i | (1 << k)];
                dp[i | (1 << k)][j + R - L] = min(dp[i | (1 << k)][j + R - L], dp[i][j] + L + R);
            }
        }
    }
    while(Q--){
        cin >> A >> L >> R;
        ll ans = 1ll << 60;
        for(int i = 0; i < 512; i++){
            if(dp.back()[i] == INF)continue;
            ll l, r, d = i - 256;
            r = (dp.back()[i] + d) / 2;
            l = (dp.back()[i] - d) / 2;
            ans = min(ans, A * n + R * r + L * l);
        }
        cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 180
memory_kb: 136912
final_rank: 8