提出 #65960870


ソースコード 拡げる

use proconio::input;
use rand::Rng;
use nalgebra::{DMatrix, DVector};
use itertools::Itertools;

fn calculate_path_probability(path: &Vec<usize>, a: &Vec<Vec<i64>>) -> f64 {
    if path.len() < 2 {
        return 0.0;
    }
    
    // パスの各遷移の確率を計算
    let mut prob = 1.0f64;
    for i in 0..path.len()-1 {
        prob *= (a[path[i]][path[i+1]] as f64) / 100.0f64;
    }
    
    prob
}

fn calculate_path_probability2(path: &Vec<usize>, a: &Vec<Vec<i64>>, first: &Vec<f64>) -> f64 {
    if path.len() < 2 {
        return 0.0;
    }
    
    // パスの各遷移の確率を計算
    let mut prob1 = first[path[0]/2 * 2];
    let mut prob2 = first[path[0]/2 * 2 + 1];
    for i in 0..path.len()-1 {
        let p1 = path[i] / 2 * 2;
        let p2 = p1 + 1;
        let n1 = path[i+1] / 2 * 2;
        let n2 = n1 + 1;

        let next_prob1 = prob1 * (a[p1][n1] as f64) + prob2 * (a[p2][n1] as f64);
        let next_prob2 = prob1 * (a[p1][n2] as f64) + prob2 * (a[p2][n2] as f64);
        prob1 = next_prob1 * 0.01;
        prob2 = next_prob2 * 0.01;
    }
    
    prob1 + prob2
}


fn run_optimization(words_and_scores: &[(String, i64)], n: usize, m: usize, l: usize) -> (f64, Vec<Vec<i64>>, Vec<char>) {
    let mut rng = rand::thread_rng();
    let mut best_score = 0.0f64;
    let mut best_a = vec![];
    let mut best_c = vec![];
    let mut best_paths = vec![];


    for _ in 0..1500 {
        // 頂点に文字を割り当て(各文字2つずつ)
        let mut c = vec!['a'; m];
        for (i, ch) in "aabbccddeeff".chars().enumerate() {
            c[i] = ch;
        }

        // 遷移確率の初期化
        let mut a = vec![vec![0i64; m]; m];
        
        // 各単語のパスを保存
        let mut word_paths = vec![];
        
        // 各単語に対して処理
        for (word, score) in words_and_scores {
            let chars: Vec<char> = word.chars().collect();
            
            // 単語の各文字に対して、使える頂点のインデックスを列挙
            let vertex_candidates: Vec<Vec<usize>> = chars.iter()
                .map(|&ch| {
                    let base_idx = ((ch as u8 - b'a') as usize) * 2;
                    vec![base_idx, base_idx + 1]
                })
                .collect();
            
            // 1つのパスを生成
            let mut path = vec![];
            for candidates in &vertex_candidates {
                let idx = rng.gen_range(0..2);
                path.push(candidates[idx]);
            }
            
            // パスを保存
            word_paths.push(path.clone());
            
            // パスに対して遷移確率を加算
            for i in 0..path.len()-1 {
                let sadd = *score;
                a[path[i]][path[i+1]] += sadd;
            }
            for i in 0..m {
                let sadd = score / (m - 1) as i64;
                if i == path[0]{
                    continue;
                }
                a[i][path[0]] += sadd / 10;
            }
        }
        
        // 確率を正規化(合計が100になるように)
        for i in 0..m {
            let row_sum: i64 = a[i].iter().sum();
            if row_sum > 0 {
                let mut remainders = vec![];
                let mut total = 0i64;
                for j in 0..m {
                    let val = (a[i][j] * 100) / row_sum;
                    a[i][j] = val;
                    total += val;
                    let remainder = (a[i][j] * row_sum * 100) % row_sum;
                    remainders.push((remainder, j));
                }
                
                remainders.sort_by(|a, b| b.0.cmp(&a.0));
                
                for (_, j) in remainders.iter().take((100 - total) as usize) {
                    a[i][*j] += 1;
                }
            } else {
                let base = 100i64 / m as i64;
                let remainder = 100i64 % m as i64;
                
                for j in 0..m {
                    a[i][j] = base;
                }
                
                for j in 0..remainder as usize {
                    a[i][j] += 1;
                }
            }
        }

        // 初期の確率を計算
        let mut first = vec![1.0 / (m as f64); m];
        for _t in 0..5 {
            let mut next_first = vec![0.0; m];
            for i in 0..m {
                for j in 0..m {
                    next_first[j] += first[i] * (a[i][j] as f64) / 100.0;
                }
            }
            first = next_first;
        }

        // この遷移確率での期待スコアを計算
        let mut total_score = 0.0f64;
        for ((_, score), path) in words_and_scores.iter().zip(word_paths.iter()) {
            let path_prob = calculate_path_probability(&path, &a);
            let trials = (l as f64) * first[path[0]] * 2.0;
            let success_prob = 1.0f64 - (1.0f64 - path_prob).powf(trials);
            total_score += success_prob * (*score as f64);
        }

        if total_score > best_score {
            best_score = total_score;
            best_a = a.clone();
            best_c = c.clone();
            best_paths = word_paths.clone();
        }
    }


    let mut current_score = best_score;
    let mut current_paths = best_paths.clone();
    let mut current_a = best_a.clone();
    
    // 焼きなましのパラメータ
    let initial_temp = 2000.0;
    let final_temp = 0.1;
    let iterations = 20000;
    
    eprintln!("Starting simulated annealing with initial score: {}", current_score);
    
    for iter in 0..iterations {
        // 温度を徐々に下げる(指数冷却)
        let progress = iter as f64 / iterations as f64;
        let temp = initial_temp * f64::powf(final_temp / initial_temp, progress);
        
        // ランダムに1つの単語を選ぶ
        let word_idx = rng.gen_range(0..n);
        let path = &current_paths[word_idx];
        
        // ランダムに1つの位置を選ぶ
        let pos = rng.gen_range(0..path.len());
        
        // その文字に対応する2つの頂点のうち、現在使っていない方を選ぶ
        let ch = words_and_scores[word_idx].0.chars().nth(pos).unwrap();
        let base_idx = ((ch as u8 - b'a') as usize) * 2;
        let new_vertex = if path[pos] == base_idx { base_idx + 1 } else { base_idx };
        
        // パスを変更して評価
        let mut new_paths = current_paths.clone();
        new_paths[word_idx][pos] = new_vertex;
        
        // 新しい遷移確率行列を生成
        let mut new_a = vec![vec![0i64; m]; m];
        for ((_, score), path) in words_and_scores.iter().zip(new_paths.iter()) {
            for i in 0..path.len()-1 {
                let sadd = score;
                new_a[path[i]][path[i+1]] += sadd;
            }
            for i in 0..m {
                let sadd = score / (m - 1) as i64;
                if i == path[0]{
                    continue;
                }
                new_a[i][path[0]] += sadd / 10;
            }
        }
        
        // 確率を正規化
        for i in 0..m {
            let row_sum: i64 = new_a[i].iter().sum();
            if row_sum > 0 {
                let mut remainders = vec![];
                let mut total = 0i64;
                for j in 0..m {
                    let val = (new_a[i][j] * 100) / row_sum;
                    new_a[i][j] = val;
                    total += val;
                    let remainder = (new_a[i][j] * row_sum * 100) % row_sum;
                    remainders.push((remainder, j));
                }
                
                remainders.sort_by(|a, b| b.0.cmp(&a.0));
                
                for (_, j) in remainders.iter().take((100 - total) as usize) {
                    new_a[i][*j] += 1;
                }
            } else {
                let base = 100i64 / m as i64;
                let remainder = 100i64 % m as i64;
                
                for j in 0..m {
                    new_a[i][j] = base;
                }
                
                for j in 0..remainder as usize {
                    new_a[i][j] += 1;
                }
            }
        }

        // 初期の確率を計算
        let mut first = vec![1.0 / (m as f64); m];
        for _t in 0..5 {
            let mut next_first = vec![0.0; m];
            for i in 0..m {
                for j in 0..m {
                    next_first[j] += first[i] * (new_a[i][j] as f64) / 100.0;
                }
            }
            first = next_first;
        }

        // 新しい遷移確率での期待スコアを計算
        let mut new_score = 0.0f64;
        for ((_, score), path) in words_and_scores.iter().zip(new_paths.iter()) {
            let path_prob = calculate_path_probability(&path, &new_a);
            let trials = (l as f64) * first[path[0]] * 2.0;
            let success_prob = 1.0f64 - (1.0f64 - path_prob).powf(trials);
            new_score += success_prob * (*score as f64);
        }

        // スコアの差分
        let score_diff = new_score - current_score;
        
        // 焼きなましの採用判定
        let accept = if score_diff > 0.0 {
            // 改善する場合は常に採用
            true
        } else {
            // 悪化する場合は確率的に採用
            let probability = f64::exp(score_diff / temp);
            rng.gen::<f64>() < probability
        };
        
        if accept {
            current_score = new_score;
            current_paths = new_paths;
            current_a = new_a.clone();  // ここでcloneを追加
            
            // 過去最高スコアの更新
            if current_score > best_score {
                best_score = current_score;
                best_paths = current_paths.clone();
                best_a = current_a.clone();
                
                if iter % 500 == 0 {
                    eprintln!("Iteration {}: New best score = {}, temp = {}", iter, best_score, temp);
                }
            }
        }
        
        // 定期的に温度を表示
        if iter % 1000 == 0 {
            eprintln!("Iteration {}: temp = {}, current_score = {}, best_score = {}", 
                     iter, temp, current_score, best_score);
        }
    }
    
    eprintln!("Simulated annealing completed. Best score: {}", best_score);

    best_score = 0.0f64;

    // 確率行列の微調整
    for _ in 0..10000 {
        // ランダムに行を選ぶ
        let i = rng.gen_range(0..m);
        
        // その行の非ゼロ要素のインデックスを集める
        let nonzero_indices: Vec<usize> = (0..m)
            .filter(|&j| best_a[i][j] > 0)
            .collect();
            
        if nonzero_indices.len() < 2 {
            continue;  // 非ゼロ要素が2未満なら次の試行へ
        }
        
        // 異なる2つの非ゼロ要素をランダムに選ぶ
        let idx1 = rng.gen_range(0..nonzero_indices.len());
        let mut idx2 = rng.gen_range(0..nonzero_indices.len());
        while idx2 == idx1 {
            idx2 = rng.gen_range(0..nonzero_indices.len());
        }
        let j1 = nonzero_indices[idx1];
        let j2 = nonzero_indices[idx2];
        
        // 確率を1移動
        let mut new_a = best_a.clone();
        new_a[i][j1] += 1;
        new_a[i][j2] -= 1;
        
        // 初期の確率を計算
        let mut first = vec![1.0 / (m as f64); m];
        for _t in 0..5 {
            let mut next_first = vec![0.0; m];
            for i in 0..m {
                for j in 0..m {
                    next_first[j] += first[i] * (new_a[i][j] as f64) / 100.0;
                }
            }
            first = next_first;
        }

        // スコアを計算
        let mut new_score = 0.0f64;
        for ((_, score), path) in words_and_scores.iter().zip(&best_paths) {
            let path_prob = calculate_path_probability2(&path, &new_a, &first);
            let trials = (l as f64);
            let success_prob = 1.0f64 - (1.0f64 - path_prob).powf(trials);
            new_score += success_prob * (*score as f64);
        }

        if new_score > best_score {
            best_score = new_score;
            best_a = new_a;  // 直接best_aを更新
        }
    }

    (best_score, best_a, best_c)
}


fn main() {
    input! {
        n: usize,
        m: usize,
        l: usize,
        words_and_scores: [(String, i64); n]
    }

    let mut best_score = 0.0f64;
    let mut best_a = vec![];
    let mut best_c = vec![];

    for i in 0..10{
        eprintln!("Starting run {}", i + 1);
        let (score, a, c) = run_optimization(&words_and_scores, n, m, l);
        eprintln!("Run {} completed with score: {}", i + 1, score);
        
        if score > best_score {
            best_score = score;
            best_a = a;
            best_c = c;
            eprintln!("New best score: {}", best_score);
        }
    }

    eprintln!("Best score after initial optimization: {}", best_score);

    // 最良の結果を出力
    for i in 0..m {
        print!("{}", best_c[i]);
        for j in 0..m {
            print!(" {}", best_a[i][j]);
        }
        println!();
    }
}

提出情報

提出日時
問題 A - Lovely Language Model
ユーザ chokudai
言語 Rust (rustc 1.70.0)
得点 6988415
コード長 13692 Byte
結果 AC
実行時間 1876 ms
メモリ 2804 KiB

コンパイルエラー

warning: unused imports: `DMatrix`, `DVector`
 --> src/main.rs:3:16
  |
3 | use nalgebra::{DMatrix, DVector};
  |                ^^^^^^^  ^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused import: `itertools::Itertools`
 --> src/main.rs:4:5
  |
4 | use itertools::Itertools;
  |     ^^^^^^^^^^^^^^^^^^^^

warning: unnecessary parentheses around assigned value
   --> src/main.rs:351:26
    |
351 |             let trials = (l as f64);
    |                          ^        ^
    |
    = note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
    |
351 -             let trials = (l as f64);
351 +             let trials = l as f64;
    |

warning: value assigned to `current_a` is never read
   --> src/main.rs:166:13
    |
166 |     let mut current_a = best_a.clone();
    |             ^^^^^^^^^
    |
    = help: maybe it is overwritten before being read?
    = note: `#[warn(unused_assignments)]` on by default

ジャッジ結果

セット名 test_ALL
得点 / 配点 6988415 / 150000000
結果
AC × 150
セット名 テストケース
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt
ケース名 結果 実行時間 メモリ
test_0000.txt AC 1796 ms 2756 KiB
test_0001.txt AC 1802 ms 2636 KiB
test_0002.txt AC 1717 ms 2764 KiB
test_0003.txt AC 1754 ms 2700 KiB
test_0004.txt AC 1853 ms 2800 KiB
test_0005.txt AC 1741 ms 2728 KiB
test_0006.txt AC 1719 ms 2760 KiB
test_0007.txt AC 1807 ms 2584 KiB
test_0008.txt AC 1790 ms 2744 KiB
test_0009.txt AC 1757 ms 2764 KiB
test_0010.txt AC 1738 ms 2628 KiB
test_0011.txt AC 1763 ms 2588 KiB
test_0012.txt AC 1799 ms 2664 KiB
test_0013.txt AC 1794 ms 2644 KiB
test_0014.txt AC 1762 ms 2696 KiB
test_0015.txt AC 1776 ms 2612 KiB
test_0016.txt AC 1760 ms 2648 KiB
test_0017.txt AC 1766 ms 2556 KiB
test_0018.txt AC 1809 ms 2680 KiB
test_0019.txt AC 1773 ms 2556 KiB
test_0020.txt AC 1743 ms 2684 KiB
test_0021.txt AC 1849 ms 2672 KiB
test_0022.txt AC 1762 ms 2764 KiB
test_0023.txt AC 1744 ms 2756 KiB
test_0024.txt AC 1790 ms 2588 KiB
test_0025.txt AC 1778 ms 2740 KiB
test_0026.txt AC 1827 ms 2704 KiB
test_0027.txt AC 1797 ms 2796 KiB
test_0028.txt AC 1833 ms 2748 KiB
test_0029.txt AC 1785 ms 2624 KiB
test_0030.txt AC 1780 ms 2764 KiB
test_0031.txt AC 1778 ms 2632 KiB
test_0032.txt AC 1745 ms 2752 KiB
test_0033.txt AC 1754 ms 2636 KiB
test_0034.txt AC 1813 ms 2688 KiB
test_0035.txt AC 1715 ms 2524 KiB
test_0036.txt AC 1746 ms 2616 KiB
test_0037.txt AC 1780 ms 2604 KiB
test_0038.txt AC 1783 ms 2616 KiB
test_0039.txt AC 1750 ms 2624 KiB
test_0040.txt AC 1777 ms 2752 KiB
test_0041.txt AC 1745 ms 2740 KiB
test_0042.txt AC 1866 ms 2632 KiB
test_0043.txt AC 1801 ms 2756 KiB
test_0044.txt AC 1743 ms 2744 KiB
test_0045.txt AC 1796 ms 2632 KiB
test_0046.txt AC 1780 ms 2752 KiB
test_0047.txt AC 1791 ms 2616 KiB
test_0048.txt AC 1748 ms 2696 KiB
test_0049.txt AC 1810 ms 2620 KiB
test_0050.txt AC 1786 ms 2736 KiB
test_0051.txt AC 1821 ms 2632 KiB
test_0052.txt AC 1749 ms 2624 KiB
test_0053.txt AC 1782 ms 2688 KiB
test_0054.txt AC 1738 ms 2748 KiB
test_0055.txt AC 1773 ms 2760 KiB
test_0056.txt AC 1744 ms 2756 KiB
test_0057.txt AC 1797 ms 2740 KiB
test_0058.txt AC 1744 ms 2708 KiB
test_0059.txt AC 1772 ms 2648 KiB
test_0060.txt AC 1789 ms 2684 KiB
test_0061.txt AC 1740 ms 2748 KiB
test_0062.txt AC 1784 ms 2616 KiB
test_0063.txt AC 1741 ms 2592 KiB
test_0064.txt AC 1739 ms 2640 KiB
test_0065.txt AC 1839 ms 2728 KiB
test_0066.txt AC 1819 ms 2620 KiB
test_0067.txt AC 1805 ms 2684 KiB
test_0068.txt AC 1755 ms 2768 KiB
test_0069.txt AC 1762 ms 2524 KiB
test_0070.txt AC 1774 ms 2620 KiB
test_0071.txt AC 1815 ms 2636 KiB
test_0072.txt AC 1748 ms 2692 KiB
test_0073.txt AC 1804 ms 2696 KiB
test_0074.txt AC 1807 ms 2636 KiB
test_0075.txt AC 1741 ms 2640 KiB
test_0076.txt AC 1745 ms 2740 KiB
test_0077.txt AC 1786 ms 2748 KiB
test_0078.txt AC 1792 ms 2632 KiB
test_0079.txt AC 1779 ms 2760 KiB
test_0080.txt AC 1857 ms 2696 KiB
test_0081.txt AC 1833 ms 2716 KiB
test_0082.txt AC 1750 ms 2616 KiB
test_0083.txt AC 1806 ms 2748 KiB
test_0084.txt AC 1795 ms 2692 KiB
test_0085.txt AC 1781 ms 2624 KiB
test_0086.txt AC 1826 ms 2612 KiB
test_0087.txt AC 1812 ms 2748 KiB
test_0088.txt AC 1827 ms 2740 KiB
test_0089.txt AC 1804 ms 2688 KiB
test_0090.txt AC 1859 ms 2620 KiB
test_0091.txt AC 1813 ms 2732 KiB
test_0092.txt AC 1754 ms 2768 KiB
test_0093.txt AC 1754 ms 2752 KiB
test_0094.txt AC 1841 ms 2800 KiB
test_0095.txt AC 1812 ms 2804 KiB
test_0096.txt AC 1773 ms 2736 KiB
test_0097.txt AC 1813 ms 2760 KiB
test_0098.txt AC 1742 ms 2756 KiB
test_0099.txt AC 1772 ms 2752 KiB
test_0100.txt AC 1797 ms 2692 KiB
test_0101.txt AC 1756 ms 2764 KiB
test_0102.txt AC 1800 ms 2680 KiB
test_0103.txt AC 1745 ms 2576 KiB
test_0104.txt AC 1754 ms 2740 KiB
test_0105.txt AC 1825 ms 2680 KiB
test_0106.txt AC 1741 ms 2620 KiB
test_0107.txt AC 1791 ms 2572 KiB
test_0108.txt AC 1773 ms 2680 KiB
test_0109.txt AC 1805 ms 2760 KiB
test_0110.txt AC 1761 ms 2548 KiB
test_0111.txt AC 1756 ms 2760 KiB
test_0112.txt AC 1804 ms 2736 KiB
test_0113.txt AC 1876 ms 2728 KiB
test_0114.txt AC 1785 ms 2768 KiB
test_0115.txt AC 1779 ms 2708 KiB
test_0116.txt AC 1747 ms 2752 KiB
test_0117.txt AC 1781 ms 2760 KiB
test_0118.txt AC 1830 ms 2600 KiB
test_0119.txt AC 1758 ms 2764 KiB
test_0120.txt AC 1844 ms 2616 KiB
test_0121.txt AC 1830 ms 2752 KiB
test_0122.txt AC 1795 ms 2752 KiB
test_0123.txt AC 1771 ms 2764 KiB
test_0124.txt AC 1777 ms 2672 KiB
test_0125.txt AC 1749 ms 2764 KiB
test_0126.txt AC 1803 ms 2744 KiB
test_0127.txt AC 1796 ms 2560 KiB
test_0128.txt AC 1754 ms 2700 KiB
test_0129.txt AC 1788 ms 2756 KiB
test_0130.txt AC 1812 ms 2700 KiB
test_0131.txt AC 1833 ms 2756 KiB
test_0132.txt AC 1731 ms 2760 KiB
test_0133.txt AC 1748 ms 2680 KiB
test_0134.txt AC 1798 ms 2592 KiB
test_0135.txt AC 1760 ms 2700 KiB
test_0136.txt AC 1849 ms 2640 KiB
test_0137.txt AC 1774 ms 2648 KiB
test_0138.txt AC 1763 ms 2588 KiB
test_0139.txt AC 1810 ms 2696 KiB
test_0140.txt AC 1812 ms 2544 KiB
test_0141.txt AC 1852 ms 2724 KiB
test_0142.txt AC 1840 ms 2672 KiB
test_0143.txt AC 1762 ms 2684 KiB
test_0144.txt AC 1793 ms 2696 KiB
test_0145.txt AC 1783 ms 2768 KiB
test_0146.txt AC 1773 ms 2552 KiB
test_0147.txt AC 1788 ms 2676 KiB
test_0148.txt AC 1788 ms 2628 KiB
test_0149.txt AC 1837 ms 2664 KiB