提出 #65959793
ソースコード 拡げる
#include <iostream>
#include <vector>
#include <string>
#include <numeric>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <chrono> // For Timer and random seed
#include <functional> // For std::function for initializers
#include <array> // For fixed-size arrays M=12
#include <limits> // For std::numeric_limits
#include <random> // For std::mt19937 as an alternative RNG, though custom Xorshift is used
// Timer for managing time limits
class Timer {
public:
Timer() : start_time_(std::chrono::high_resolution_clock::now()) {}
void reset() {
start_time_ = std::chrono::high_resolution_clock::now();
}
double get_elapsed_seconds() const {
auto now = std::chrono::high_resolution_clock::now();
return std::chrono::duration<double>(now - start_time_).count();
}
private:
std::chrono::time_point<std::chrono::high_resolution_clock> start_time_;
};
// Problem Constraints are fixed
constexpr int N_FIXED = 36;
constexpr int M_FIXED = 12;
constexpr int MAX_S_LEN_FIXED = 12;
constexpr int CHAR_COUNT = 6; // 'a' through 'f'
// SA Parameters
constexpr int K_POWER_STATIONARY_DIST = 32; // MODIFIED from 64
constexpr int INITIAL_MAX_DELTA_A_TRANSFER = 20; // Max % to transfer in one A_ij move initially
// New constants for improved moves & strategy
constexpr double Q_K_EPSILON = 1e-9; // MODIFIED from 1e-6
constexpr int INITIAL_STRING_FOCUS_MAX_DELTA = 10; // New constant for adaptive string focus delta
constexpr int ENHANCED_C_NUM_PREDECESSORS_TO_UPDATE = 3; // How many predecessors to update after a C_k change
constexpr int STRING_FOCUS_W_CANDIDATES = 3; // How many low/high utility transitions to consider for smart moves
// Precomputed data structure
struct GlobalPrecomputedData {
// string_char_pairs_locations[c1-'a'][c2-'a'] stores {string_index, char_start_pos_in_that_string}
std::array<std::array<std::vector<std::pair<int, int>>, CHAR_COUNT>, CHAR_COUNT> string_char_pairs_locations;
void precompute(const std::array<std::string, N_FIXED>& S_arr) {
for (int c1 = 0; c1 < CHAR_COUNT; ++c1) {
for (int c2 = 0; c2 < CHAR_COUNT; ++c2) {
string_char_pairs_locations[c1][c2].clear();
}
}
for (int k_idx = 0; k_idx < N_FIXED; ++k_idx) {
const auto& Sk = S_arr[k_idx];
if (Sk.length() < 2) continue;
for (size_t char_idx = 0; char_idx < Sk.length() - 1; ++char_idx) {
char ch1 = Sk[char_idx];
char ch2 = Sk[char_idx+1];
// Ensure characters are within 'a' to 'f'
if (ch1 >= 'a' && ch1 < ('a' + CHAR_COUNT) && ch2 >= 'a' && ch2 < ('a' + CHAR_COUNT)) {
string_char_pairs_locations[ch1-'a'][ch2-'a'].emplace_back(k_idx, static_cast<int>(char_idx));
}
}
}
}
};
// Structure to hold problem input
struct ProblemInput {
std::array<std::string, N_FIXED> S;
std::array<int, N_FIXED> P;
int N_read, M_read; // Actual N, M from input (though fixed for this problem)
double L; // Length of generated string (using double for 10^6 to match type in ScoreCalculator)
void read() {
std::cin >> N_read >> M_read >> L;
for (int i = 0; i < N_FIXED; ++i) {
std::cin >> S[i] >> P[i];
}
}
};
// Solution structure
struct Solution {
std::array<char, M_FIXED> C;
std::array<std::array<int, M_FIXED>, M_FIXED> A;
Solution() {
if (M_FIXED > 0) { // Default constructor: uniform A, 'a' for C
for (int i = 0; i < M_FIXED; ++i) {
C[i] = 'a';
if (M_FIXED == 0) continue; // Should not happen if M_FIXED > 0 check passes
int base_prob = 100 / M_FIXED;
int remainder = 100 % M_FIXED;
for(int j_col=0; j_col < M_FIXED; ++j_col) A[i][j_col] = base_prob;
for(int j_col=0; j_col < remainder; ++j_col) A[i][j_col]++;
}
}
}
void print() const {
std::cout << std::fixed << std::setprecision(0); // Ensure integers are printed as integers
for (int i = 0; i < M_FIXED; ++i) {
std::cout << C[i];
for (int j = 0; j < M_FIXED; ++j) {
std::cout << " " << A[i][j];
}
std::cout << std::endl;
}
}
};
// Basic Xorshift RNG
struct Random {
unsigned int x, y, z, w;
Random(unsigned int seed) : x(seed), y(362436069), z(521288629), w(88675123) {
if (seed == 0) x = 123456789; // Ensure x is not 0 if seed is 0
if (y == 0) y = 362436069; // Default non-zero if somehow initialized to 0
if (z == 0) z = 521288629;
if (w == 0) w = 88675123;
}
using result_type = unsigned int;
static constexpr result_type min() { return 0; }
static constexpr result_type max() { return std::numeric_limits<unsigned int>::max(); }
unsigned int next_int_internal() {
unsigned int t = x ^ (x << 11);
x = y; y = z; z = w;
w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
return w;
}
result_type operator()() { return next_int_internal(); }
double next_double() { // Returns [0.0, 1.0)
return static_cast<double>(next_int_internal()) / (static_cast<double>(max()) + 1.0);
}
int next_int_range(int min_val, int max_val) { // Returns [min_val, max_val]
if (min_val > max_val) return min_val; // Or throw error, but for CP, this is safer
return min_val + next_int_internal() % (max_val - min_val + 1);
}
};
// M_FIXED x M_FIXED matrix of doubles
using MatrixM_Double = std::array<std::array<double, M_FIXED>, M_FIXED>;
MatrixM_Double multiply_matrices(const MatrixM_Double& A_mat, const MatrixM_Double& B_mat) {
MatrixM_Double C_mat{}; // Value-initialize to zeros
if (M_FIXED == 0) return C_mat;
for (int i = 0; i < M_FIXED; ++i) {
for (int j = 0; j < M_FIXED; ++j) {
double sum = 0.0;
for (int l = 0; l < M_FIXED; ++l) {
sum += A_mat[i][l] * B_mat[l][j];
}
C_mat[i][j] = sum;
}
}
return C_mat;
}
MatrixM_Double matrix_pow(MatrixM_Double base_matrix, int power) {
MatrixM_Double res{}; // Value-initialize to zeros
if (M_FIXED == 0) return res;
for (int i = 0; i < M_FIXED; ++i) res[i][i] = 1.0; // Identity matrix
while (power > 0) {
if (power % 2 == 1) res = multiply_matrices(res, base_matrix);
base_matrix = multiply_matrices(base_matrix, base_matrix);
power /= 2;
}
return res;
}
class ScoreCalculator {
public:
const ProblemInput& input_ref;
// Cached members to avoid reallocations or repeated calculations within one score call
std::array<double, M_FIXED> pi_dist_cached;
MatrixM_Double A_double_cached;
// p_sk_dp[char_idx_in_sk][state_idx] = prob of S_k[0...char_idx_in_sk] ending in state_idx
std::array<std::array<double, M_FIXED>, MAX_S_LEN_FIXED> p_sk_dp;
ScoreCalculator(const ProblemInput& prob_input) : input_ref(prob_input) {}
std::pair<double, std::array<double, N_FIXED>> calculate_score_with_Qk(const Solution& sol) {
if (M_FIXED == 0) return {0.0, {}}; // Or handle as per problem for M=0
// Convert A (int percentages) to A_double_cached (double probabilities)
for (int i = 0; i < M_FIXED; ++i) {
for (int j = 0; j < M_FIXED; ++j) {
A_double_cached[i][j] = sol.A[i][j] / 100.0;
}
}
// Approximate stationary distribution pi_dist_cached from state 0
MatrixM_Double A_pow_K = matrix_pow(A_double_cached, K_POWER_STATIONARY_DIST);
for (int j = 0; j < M_FIXED; ++j) {
pi_dist_cached[j] = A_pow_K[0][j]; // Probability of being in state j after K steps, starting from state 0
}
// Normalize pi_dist_cached (should sum to 1 ideally, but float precision)
double sum_pi_val = 0.0;
for(int j=0; j < M_FIXED; ++j) sum_pi_val += pi_dist_cached[j];
if (sum_pi_val > 1e-9) { // Avoid division by zero if sum is tiny
for (int j=0; j < M_FIXED; ++j) pi_dist_cached[j] /= sum_pi_val;
} else { // If sum is effectively zero (e.g. state 0 is a sink with no escape or all paths die)
std::fill(pi_dist_cached.begin(), pi_dist_cached.end(), 0.0);
if (M_FIXED > 0) pi_dist_cached[0] = 1.0; // Fallback: assume always in state 0 (arbitrary, but needs a dist)
}
double total_expected_preference = 0;
std::array<double, N_FIXED> Q_k_values; // To store Q_k for each S_k
for (int k_idx = 0; k_idx < N_FIXED; ++k_idx) {
const std::string& Sk = input_ref.S[k_idx];
int Sk_len = Sk.length();
if (Sk_len == 0) {
Q_k_values[k_idx] = 0.0;
continue;
}
// DP to calculate P(Sk starts at a random position | stationary dist)
// p_sk_dp[char_idx][state_u] = P(Sk[0...char_idx] is generated AND ends in state_u)
for (int u = 0; u < M_FIXED; ++u) { // Base case for Sk[0]
if (sol.C[u] == Sk[0]) {
p_sk_dp[0][u] = pi_dist_cached[u];
} else {
p_sk_dp[0][u] = 0.0;
}
}
for (int char_idx = 0; char_idx < Sk_len - 1; ++char_idx) { // DP transitions for Sk[1]...Sk[len-1]
for (int v_next_state = 0; v_next_state < M_FIXED; ++v_next_state) {
p_sk_dp[char_idx+1][v_next_state] = 0.0;
if (sol.C[v_next_state] == Sk[char_idx+1]) {
double sum_prev_paths = 0.0;
for (int u_curr_state = 0; u_curr_state < M_FIXED; ++u_curr_state) {
// P(Sk[0...char_idx] ends u_curr_state) * P(transition u_curr_state -> v_next_state)
sum_prev_paths += p_sk_dp[char_idx][u_curr_state] * A_double_cached[u_curr_state][v_next_state];
}
p_sk_dp[char_idx+1][v_next_state] = sum_prev_paths;
}
}
}
double prob_Sk_starts_at_random_pos = 0; // Sum over all states for the last char of Sk
for (int u = 0; u < M_FIXED; ++u) {
prob_Sk_starts_at_random_pos += p_sk_dp[Sk_len-1][u];
}
// Using Poisson approximation for Q_k (prob S_k appears at least once)
double lambda_k = input_ref.L * prob_Sk_starts_at_random_pos; // Expected occurrences
double Q_k;
// Handle lambda_k extremes for stability and correctness
if (prob_Sk_starts_at_random_pos < 1e-100 || lambda_k < 1e-9) { // Effectively zero probability
Q_k = lambda_k; // For small x, 1 - e^-x approx x
} else if (lambda_k > 30) { // For large lambda_k, e^-lambda_k is effectively 0
Q_k = 1.0;
} else {
Q_k = -std::expm1(-lambda_k); // Equivalent to 1.0 - std::exp(-lambda_k) but more accurate for small lambda_k
}
if (std::isnan(Q_k) || Q_k < 0) Q_k = 0.0; // Safety checks
if (Q_k > 1.0) Q_k = 1.0;
Q_k_values[k_idx] = Q_k;
total_expected_preference += input_ref.P[k_idx] * Q_k;
}
return {total_expected_preference, Q_k_values};
}
};
// Normalizes a row of A based on proportions W_row, ensuring sum is 100.
void normalize_row_A(std::array<int, M_FIXED>& A_row, const std::array<double, M_FIXED>& W_row_proportions, Random& rnd) {
if (M_FIXED == 0) return;
double sum_proportions = 0;
for(double p : W_row_proportions) sum_proportions += p;
if (sum_proportions < 1e-9) { // If all proportions are near zero, distribute uniformly
int base_prob = 100 / M_FIXED;
int remainder = 100 % M_FIXED;
for (int j = 0; j < M_FIXED; ++j) A_row[j] = base_prob;
for (int j = 0; j < remainder; ++j) A_row[j]++;
return;
}
std::vector<std::pair<double, int>> fractional_parts_vec(M_FIXED);
int current_sum_A_int_parts = 0;
for (int j = 0; j < M_FIXED; ++j) {
double exact_val = 100.0 * W_row_proportions[j] / sum_proportions;
A_row[j] = static_cast<int>(exact_val);
// Add small random jitter to fractional part for tie-breaking
fractional_parts_vec[j] = {exact_val - A_row[j] + rnd.next_double() * 1e-7, j};
current_sum_A_int_parts += A_row[j];
}
int diff_to_distribute = 100 - current_sum_A_int_parts;
// Distribute remainder based on fractional parts
if (diff_to_distribute != 0) {
if (diff_to_distribute > 0) { // Need to add
std::sort(fractional_parts_vec.rbegin(), fractional_parts_vec.rend()); // Sort descending by fractional part
for (int k = 0; k < diff_to_distribute; ++k) {
bool distributed_one = false;
// Try to distribute to states with largest fractional parts, respecting A[j] <= 100
for(int attempt = 0; attempt < M_FIXED; ++attempt) {
int target_j = fractional_parts_vec[(k + attempt) % M_FIXED].second;
if (A_row[target_j] < 100) {
A_row[target_j]++;
distributed_one = true;
break;
}
}
if (!distributed_one && M_FIXED > 0) { /* All viable states are 100. Sum should be 100*M_FIXED. Error if still need to add. */ break; }
}
} else { // Need to subtract (diff_to_distribute is negative)
std::sort(fractional_parts_vec.begin(), fractional_parts_vec.end()); // Sort ascending by fractional part
for (int k = 0; k < -diff_to_distribute; ++k) {
bool distributed_one = false;
// Try to take from states with smallest fractional parts, respecting A[j] >= 0
for(int attempt = 0; attempt < M_FIXED; ++attempt) {
int target_j = fractional_parts_vec[(k + attempt) % M_FIXED].second;
if (A_row[target_j] > 0) {
A_row[target_j]--;
distributed_one = true;
break;
}
}
if (!distributed_one && M_FIXED > 0) { /* All viable states are 0. Sum should be 0. Error if still need to subtract. */ break; }
}
}
}
// Final pass to fix any sum discrepancy due to all states being 0 or 100, or float issues
int current_sum_final = 0;
for(int val : A_row) current_sum_final += val;
int final_diff = 100 - current_sum_final;
if (final_diff != 0 && M_FIXED > 0) {
std::vector<int> p_indices(M_FIXED);
std::iota(p_indices.begin(), p_indices.end(), 0);
for(size_t sh_i = 0; sh_i < p_indices.size(); ++sh_i) {
if (p_indices.empty() || sh_i >= p_indices.size() -1 && sh_i != 0) break; // Avoid issue if size is 0 or 1
std::swap(p_indices[sh_i], p_indices[rnd.next_int_range(sh_i, p_indices.size()-1)]);
}
if (final_diff > 0) { // Need to add more
for (int k_adj = 0; k_adj < final_diff; ++k_adj) {
bool success_inc = false;
for (int idx_to_inc : p_indices) { // Iterate through shuffled indices
if (A_row[idx_to_inc] < 100) {
A_row[idx_to_inc]++;
success_inc = true;
break;
}
}
// This fallback should ideally not be needed if logic above is perfect and M_FIXED > 0.
if (!success_inc) { A_row[p_indices[rnd.next_int_range(0,M_FIXED-1)]]++; }
}
} else { // Need to subtract more (final_diff < 0)
for (int k_adj = 0; k_adj < -final_diff; ++k_adj) {
bool success_dec = false;
for (int idx_to_dec : p_indices) { // Iterate through shuffled indices
if (A_row[idx_to_dec] > 0) {
A_row[idx_to_dec]--;
success_dec = true;
break;
}
}
if (!success_dec ) { A_row[p_indices[rnd.next_int_range(0,M_FIXED-1)]]--; }
}
}
}
}
// Updates row A[i_state] based on current Qk values and character assignments
void update_row_A_from_adaptive_heuristic(int i_state, Solution& sol_being_built,
const ProblemInput& input, Random& rnd,
const std::array<double, N_FIXED>& qk_values_of_current_eval,
const GlobalPrecomputedData& precomputed) {
if (M_FIXED == 0) return;
std::array<double, M_FIXED> W_row; // Proportions for transitions from i_state
std::fill(W_row.begin(), W_row.end(), 0.0);
char Ci = sol_being_built.C[i_state];
for (int j_next_state = 0; j_next_state < M_FIXED; ++j_next_state) {
char Cj = sol_being_built.C[j_next_state];
double sum_score_weights = 1e-9; // Start with a small epsilon to avoid all-zero weights
// Check if characters are valid indices
if (Ci >= 'a' && Ci < ('a' + CHAR_COUNT) && Cj >= 'a' && Cj < ('a' + CHAR_COUNT)) {
const auto& relevant_pairs = precomputed.string_char_pairs_locations[Ci-'a'][Cj-'a'];
for (const auto& p_info : relevant_pairs) {
int k_idx = p_info.first; // String index
// Weight by preference and how much Q_k can still improve (1 - Q_k)
sum_score_weights += input.P[k_idx] * (1.0 - qk_values_of_current_eval[k_idx] + Q_K_EPSILON);
}
}
W_row[j_next_state] = sum_score_weights;
}
normalize_row_A(sol_being_built.A[i_state], W_row, rnd);
}
enum class InitializerType { C_ONLY, C_AND_A };
struct InitializerMeta {
InitializerType type;
std::function<void(Solution&, Random&, const ProblemInput&, const GlobalPrecomputedData&)> func;
std::string name;
};
void solve(const ProblemInput& input,
const GlobalPrecomputedData& precomputed,
Solution& best_sol_for_this_run, // Output: best solution found in this SA run
double& best_score_for_this_run, // Output: its score
std::array<double, N_FIXED>& best_Q_k_for_this_run, // Output: its Q_k values
Random& rnd,
const Timer& /* run_timer_overall_progress */, // Unused directly, SA uses its own timer for this run
double time_limit_for_this_sa_run,
const InitializerMeta& initializer_meta
)
{
Solution current_sol;
ScoreCalculator score_calc(input);
// Initialize solution (C and possibly A)
if (initializer_meta.type == InitializerType::C_AND_A) {
initializer_meta.func(current_sol, rnd, input, precomputed);
} else { // C_ONLY
initializer_meta.func(current_sol, rnd, input, precomputed);
// For C_ONLY initializers, A matrix needs to be initialized.
// Use adaptive heuristic with dummy Q_k (all zeros, meaning all strings are equally "needed")
std::array<double, N_FIXED> initial_dummy_qk;
std::fill(initial_dummy_qk.begin(), initial_dummy_qk.end(), 0.0);
for (int i = 0; i < M_FIXED; ++i) {
update_row_A_from_adaptive_heuristic(i, current_sol, input, rnd, initial_dummy_qk, precomputed);
}
}
auto score_and_qk = score_calc.calculate_score_with_Qk(current_sol);
best_score_for_this_run = score_and_qk.first;
best_sol_for_this_run = current_sol;
best_Q_k_for_this_run = score_and_qk.second;
double current_score_val = best_score_for_this_run;
std::array<double, N_FIXED> current_Q_k_values = best_Q_k_for_this_run;
// SA temperature schedule
double initial_temp_heuristic = std::abs(best_score_for_this_run);
if (initial_temp_heuristic < 1.0 && initial_temp_heuristic >=0.0) {
double sum_P = 0; for(int p_val : input.P) sum_P += p_val; // MODIFIED: Use sum_P
initial_temp_heuristic = sum_P * 0.01;
if (initial_temp_heuristic < 1.0) initial_temp_heuristic = 1000.0;
}
else if (initial_temp_heuristic < 1.0) initial_temp_heuristic = 1000.0; // Handles negative scores
double initial_temp = std::max(100.0, initial_temp_heuristic * 0.05);
if (initial_temp <= 1e-9) initial_temp = 1000.0; // Safety for zero/negative scores
double final_temp = 0.1;
Timer sa_iteration_timer; // Timer for this specific SA run's duration
while(true) {
double elapsed_this_sa_run = sa_iteration_timer.get_elapsed_seconds();
if (elapsed_this_sa_run >= time_limit_for_this_sa_run) break;
// Progress for temperature annealing and move adaptation
double progress = std::min(1.0, std::max(0.0, elapsed_this_sa_run / time_limit_for_this_sa_run));
double temp_ratio_exponent = progress * progress; // Standard cooling schedule
double temp = initial_temp * std::pow(final_temp / initial_temp, temp_ratio_exponent);
temp = std::max(final_temp, temp); // Ensure temp doesn't go below final_temp
Solution next_sol = current_sol;
double move_type_rand = rnd.next_double();
// Define probabilities for different types of moves
constexpr double PROB_C_CHANGE_SINGLE = 0.15;
constexpr double PROB_C_SWAP_PAIR = 0.10; // New move: Swap C for two states
constexpr double PROB_A_TRANSFER_PAIR = 0.40; // Transfer A[i][j1] <-> A[i][j2]
constexpr double PROB_A_TRANSFER_SMART_SUBTYPE_RATIO = 0.55;
constexpr double PROB_RECOMPUTE_ROW_A = 0.15;
// Remainder (0.20) for String-Focused A_ij Adjustment
if (move_type_rand < PROB_C_CHANGE_SINGLE) {
if (M_FIXED == 0) continue;
int k_state = rnd.next_int_range(0, M_FIXED - 1);
char old_Ck = next_sol.C[k_state];
char new_Ck = 'a' + rnd.next_int_range(0, CHAR_COUNT - 1);
if (new_Ck == old_Ck && CHAR_COUNT > 1) { // Ensure char actually changes if possible
new_Ck = 'a' + ( (old_Ck - 'a' + 1 + rnd.next_int_range(0, CHAR_COUNT - 2) ) % CHAR_COUNT );
}
if (CHAR_COUNT == 0) new_Ck = 'a'; // Safety
else if (new_Ck < 'a' || new_Ck >= ('a' + CHAR_COUNT)) new_Ck = 'a'; // Safety for CHAR_COUNT=0 or bad range
next_sol.C[k_state] = new_Ck;
// Update outgoing transitions for k_state
update_row_A_from_adaptive_heuristic(k_state, next_sol, input, rnd, current_Q_k_values, precomputed);
// Update some important predecessors' outgoing transitions
std::vector<int> predecessors_to_update;
for (int i = 0; i < M_FIXED; ++i) {
if (i == k_state) continue;
if (current_sol.A[i][k_state] > 20) {
predecessors_to_update.push_back(i);
}
}
if (!predecessors_to_update.empty()) {
for(size_t sh_i = 0; sh_i < predecessors_to_update.size(); ++sh_i) {
if (predecessors_to_update.empty() || sh_i >= predecessors_to_update.size() -1 && sh_i != 0) break;
std::swap(predecessors_to_update[sh_i], predecessors_to_update[rnd.next_int_range(sh_i, predecessors_to_update.size()-1)]);
}
for(int count=0; count < std::min((int)predecessors_to_update.size(), ENHANCED_C_NUM_PREDECESSORS_TO_UPDATE); ++count) {
update_row_A_from_adaptive_heuristic(predecessors_to_update[count], next_sol, input, rnd, current_Q_k_values, precomputed);
}
}
} else if (move_type_rand < PROB_C_CHANGE_SINGLE + PROB_C_SWAP_PAIR) { // C_SWAP_PAIR Move
if (M_FIXED < 2) continue;
int k1 = rnd.next_int_range(0, M_FIXED - 1);
int k2 = rnd.next_int_range(0, M_FIXED - 1);
if (k1 == k2) { // Ensure k1 and k2 are different
if (M_FIXED > 1) k2 = (k1 + 1 + rnd.next_int_range(0, M_FIXED - 2)) % M_FIXED;
else continue; // Should not happen if M_FIXED < 2 check passes
}
std::swap(next_sol.C[k1], next_sol.C[k2]);
update_row_A_from_adaptive_heuristic(k1, next_sol, input, rnd, current_Q_k_values, precomputed);
update_row_A_from_adaptive_heuristic(k2, next_sol, input, rnd, current_Q_k_values, precomputed);
std::vector<int> predecessors_to_update;
std::vector<bool> already_added(M_FIXED, false);
for (int i = 0; i < M_FIXED; ++i) {
if (i == k1 || i == k2) continue;
if (current_sol.A[i][k1] > 20 && !already_added[i]) { // Check against old k1 (now occupied by k2's char)
predecessors_to_update.push_back(i);
already_added[i] = true;
}
if (current_sol.A[i][k2] > 20 && !already_added[i]) { // Check against old k2 (now occupied by k1's char)
predecessors_to_update.push_back(i);
already_added[i] = true;
}
}
if (!predecessors_to_update.empty()) {
for(size_t sh_i = 0; sh_i < predecessors_to_update.size(); ++sh_i) {
if (predecessors_to_update.empty() || sh_i >= predecessors_to_update.size() -1 && sh_i != 0) break;
std::swap(predecessors_to_update[sh_i], predecessors_to_update[rnd.next_int_range(sh_i, predecessors_to_update.size()-1)]);
}
for(int count=0; count < std::min((int)predecessors_to_update.size(), ENHANCED_C_NUM_PREDECESSORS_TO_UPDATE); ++count) {
update_row_A_from_adaptive_heuristic(predecessors_to_update[count], next_sol, input, rnd, current_Q_k_values, precomputed);
}
}
} else if (move_type_rand < PROB_C_CHANGE_SINGLE + PROB_C_SWAP_PAIR + PROB_A_TRANSFER_PAIR) { // A_TRANSFER_PAIR Move
if (M_FIXED == 0) continue;
if (M_FIXED < 2 && rnd.next_double() <= PROB_A_TRANSFER_SMART_SUBTYPE_RATIO ) { // Smart subtype needs M_FIXED >=2
continue;
}
int i_state = rnd.next_int_range(0, M_FIXED - 1);
int j1 = -1, j2 = -1;
bool is_smart_transfer_subtype = (M_FIXED >=2 && rnd.next_double() <= PROB_A_TRANSFER_SMART_SUBTYPE_RATIO);
if (!is_smart_transfer_subtype) {
j1 = rnd.next_int_range(0, M_FIXED - 1);
if (M_FIXED > 1) {
j2 = rnd.next_int_range(0, M_FIXED - 1);
if (j1 == j2) j2 = (j1 + 1 + rnd.next_int_range(0, M_FIXED - 2)) % M_FIXED;
} else { // M_FIXED == 1
j2 = j1; // No other choice, this move will be a no-op or fail delta constraint.
}
} else { // Smart transfer subtype (requires M_FIXED >= 2, ensured by is_smart_transfer_subtype condition)
std::array<double, M_FIXED> W_row_smart;
char Ci_smart = next_sol.C[i_state];
for (int j_idx = 0; j_idx < M_FIXED; ++j_idx) {
char Cj_smart = next_sol.C[j_idx];
double sum_score_weights = 1e-9;
if (Ci_smart >= 'a' && Ci_smart < ('a'+CHAR_COUNT) && Cj_smart >= 'a' && Cj_smart < ('a'+CHAR_COUNT)) {
const auto& relevant_pairs = precomputed.string_char_pairs_locations[Ci_smart-'a'][Cj_smart-'a'];
for (const auto& p_info : relevant_pairs) {
int k_s_idx = p_info.first;
sum_score_weights += input.P[k_s_idx] * (1.0 - current_Q_k_values[k_s_idx] + Q_K_EPSILON);
}
}
W_row_smart[j_idx] = sum_score_weights;
}
std::vector<int> cand_j1, cand_j2_all;
for(int j=0; j < M_FIXED; ++j) {
if (next_sol.A[i_state][j] > 0) cand_j1.push_back(j);
if (next_sol.A[i_state][j] < 100) cand_j2_all.push_back(j);
}
if (cand_j1.empty() || cand_j2_all.empty()) continue;
std::sort(cand_j1.begin(), cand_j1.end(), [&](int a, int b){ return W_row_smart[a] < W_row_smart[b]; });
int j1_max_idx = std::min((int)cand_j1.size() - 1, STRING_FOCUS_W_CANDIDATES -1);
if (j1_max_idx < 0) continue;
j1 = cand_j1[rnd.next_int_range(0, j1_max_idx)];
std::vector<int> cand_j2;
for(int val : cand_j2_all) if(val != j1) cand_j2.push_back(val);
if (cand_j2.empty()) continue;
std::sort(cand_j2.begin(), cand_j2.end(), [&](int a, int b){ return W_row_smart[a] > W_row_smart[b]; });
int j2_max_idx = std::min((int)cand_j2.size() - 1, STRING_FOCUS_W_CANDIDATES -1);
if (j2_max_idx < 0) continue;
j2 = cand_j2[rnd.next_int_range(0, j2_max_idx)];
}
if (j1 == -1 || j2 == -1 || (j1 == j2 && M_FIXED > 1) ) continue;
if (j1 == j2 && M_FIXED == 1) { /* This is fine for M=1, delta will be 0 or move rejected */ }
int current_max_delta_val = std::max(1, static_cast<int>(INITIAL_MAX_DELTA_A_TRANSFER * std::sqrt(1.0 - progress) + 0.5));
// current_max_delta_val = std::max(1, current_max_delta_val); // already done by std::max(1, ...)
int delta;
bool transfer_j1_to_j2;
if(is_smart_transfer_subtype) {
transfer_j1_to_j2 = (rnd.next_double() < 0.75);
} else {
transfer_j1_to_j2 = (rnd.next_double() < 0.5);
}
if (j1 == j2) { // If only one state (M_FIXED=1) or bad luck in random choice for M_FIXED > 1 non-smart
continue; // No transfer possible
}
if (transfer_j1_to_j2) {
int max_d = std::min({current_max_delta_val, next_sol.A[i_state][j1], 100 - next_sol.A[i_state][j2]});
if (max_d <= 0) continue;
delta = rnd.next_int_range(1, max_d);
next_sol.A[i_state][j1] -= delta;
next_sol.A[i_state][j2] += delta;
} else {
int max_d = std::min({current_max_delta_val, next_sol.A[i_state][j2], 100 - next_sol.A[i_state][j1]});
if (max_d <= 0) continue;
delta = rnd.next_int_range(1, max_d);
next_sol.A[i_state][j2] -= delta;
next_sol.A[i_state][j1] += delta;
}
} else if (move_type_rand < PROB_C_CHANGE_SINGLE + PROB_C_SWAP_PAIR + PROB_A_TRANSFER_PAIR + PROB_RECOMPUTE_ROW_A) {
if (M_FIXED == 0) continue;
int i_state = rnd.next_int_range(0, M_FIXED - 1);
update_row_A_from_adaptive_heuristic(i_state, next_sol, input, rnd, current_Q_k_values, precomputed);
} else { // String-Focused A_ij Adjustment
if (M_FIXED == 0 || N_FIXED == 0) continue;
std::vector<double> string_weights(N_FIXED);
double total_string_weight = 0;
for (int k = 0; k < N_FIXED; ++k) {
string_weights[k] = input.P[k] * (1.0 - current_Q_k_values[k] + Q_K_EPSILON);
if (string_weights[k] < 0) string_weights[k] = Q_K_EPSILON * input.P[k];
total_string_weight += string_weights[k];
}
if (total_string_weight < 1e-9) continue;
int k_idx_focus = N_FIXED -1;
double r_select_str = rnd.next_double() * total_string_weight;
double cumulative_weight = 0;
for (int k = 0; k < N_FIXED; ++k) {
cumulative_weight += string_weights[k];
if (r_select_str <= cumulative_weight) {
k_idx_focus = k;
break;
}
}
const auto& Sk_focus = input.S[k_idx_focus];
if (Sk_focus.length() < 2) continue;
int char_pair_start_idx = rnd.next_int_range(0, Sk_focus.length() - 2);
char target_C1 = Sk_focus[char_pair_start_idx];
char target_C2 = Sk_focus[char_pair_start_idx+1];
std::vector<std::pair<int, int>> candidate_uv_pairs;
for (int u_s = 0; u_s < M_FIXED; ++u_s) {
if (next_sol.C[u_s] == target_C1) {
for (int v_s = 0; v_s < M_FIXED; ++v_s) {
if (next_sol.C[v_s] == target_C2) {
candidate_uv_pairs.push_back({u_s, v_s});
}
}
}
}
if (candidate_uv_pairs.empty()) continue;
std::pair<int,int> uv_to_boost = candidate_uv_pairs[rnd.next_int_range(0, candidate_uv_pairs.size()-1)];
int u_focus = uv_to_boost.first;
int v_focus = uv_to_boost.second;
// MODIFIED: Adaptive delta for string focus move
int current_max_delta_focus = std::max(1, static_cast<int>(INITIAL_STRING_FOCUS_MAX_DELTA * std::sqrt(1.0 - progress) + 0.5));
// if (current_max_delta_focus <= 0) current_max_delta_focus = 1; // Already handled by std::max(1,...)
int delta_s = rnd.next_int_range(1, current_max_delta_focus);
delta_s = std::min(delta_s, 100 - next_sol.A[u_focus][v_focus]);
if (delta_s <= 0) continue;
std::vector<int> candidates_w_indices;
for (int w_s = 0; w_s < M_FIXED; ++w_s) {
if (w_s != v_focus && next_sol.A[u_focus][w_s] >= delta_s) {
candidates_w_indices.push_back(w_s);
}
}
if (candidates_w_indices.empty()) {
int max_available_from_any_w = 0;
for (int w_s = 0; w_s < M_FIXED; ++w_s) {
if (w_s != v_focus) max_available_from_any_w = std::max(max_available_from_any_w, next_sol.A[u_focus][w_s]);
}
delta_s = std::min(delta_s, max_available_from_any_w);
if (delta_s <= 0) continue;
candidates_w_indices.clear();
for (int w_s = 0; w_s < M_FIXED; ++w_s) {
if (w_s != v_focus && next_sol.A[u_focus][w_s] >= delta_s) { // Use the new, possibly smaller delta_s
candidates_w_indices.push_back(w_s);
}
}
if (candidates_w_indices.empty()) continue;
}
int w_focus = -1;
std::vector<std::pair<double, int>> w_importances;
char Char_u_focus = next_sol.C[u_focus];
for (int w_cand_idx : candidates_w_indices) {
char Char_w_cand = next_sol.C[w_cand_idx];
double importance_score = 1e-9;
if (Char_u_focus >= 'a' && Char_u_focus < ('a'+CHAR_COUNT) && Char_w_cand >= 'a' && Char_w_cand < ('a'+CHAR_COUNT)) {
const auto& relevant_pairs = precomputed.string_char_pairs_locations[Char_u_focus-'a'][Char_w_cand-'a'];
for (const auto& p_info : relevant_pairs) {
int sk_idx = p_info.first;
importance_score += input.P[sk_idx] * (1.0 - current_Q_k_values[sk_idx] + Q_K_EPSILON);
}
}
w_importances.push_back({importance_score, w_cand_idx});
}
if (w_importances.empty()) continue;
std::sort(w_importances.begin(), w_importances.end());
int num_least_important_to_consider = std::min((int)w_importances.size(), STRING_FOCUS_W_CANDIDATES);
if (num_least_important_to_consider == 0) continue; // Should be caught by w_importances.empty()
w_focus = w_importances[rnd.next_int_range(0, num_least_important_to_consider - 1)].second;
next_sol.A[u_focus][v_focus] += delta_s;
next_sol.A[u_focus][w_focus] -= delta_s;
}
auto next_score_qk_pair = score_calc.calculate_score_with_Qk(next_sol);
double next_score_eval = next_score_qk_pair.first;
if (next_score_eval > current_score_val || (temp > 1e-9 && rnd.next_double() < std::exp((next_score_eval - current_score_val) / temp)) ) {
current_sol = next_sol;
current_score_val = next_score_eval;
current_Q_k_values = next_score_qk_pair.second;
if (current_score_val > best_score_for_this_run) {
best_score_for_this_run = current_score_val;
best_sol_for_this_run = current_sol;
best_Q_k_for_this_run = current_Q_k_values;
}
}
}
}
// Initializer Implementations
void C_init_weighted_random(Solution& sol, Random& rnd, const ProblemInput& input, const GlobalPrecomputedData& /*precomputed*/) {
if (M_FIXED == 0) return;
if (CHAR_COUNT == 0) {
for(int i=0; i<M_FIXED; ++i) sol.C[i] = 'a';
return;
}
std::array<double, CHAR_COUNT> char_weights;
std::fill(char_weights.begin(), char_weights.end(), 0.0);
for(int i=0; i < N_FIXED; ++i) {
std::array<bool, CHAR_COUNT> char_seen_in_Sk{};
for(char ch_in_Sk : input.S[i]) {
if (ch_in_Sk >= 'a' && ch_in_Sk < ('a' + CHAR_COUNT)) {
if (!char_seen_in_Sk[ch_in_Sk - 'a']) {
char_weights[ch_in_Sk - 'a'] += input.P[i];
char_seen_in_Sk[ch_in_Sk - 'a'] = true;
}
}
}
}
double total_weight = 0;
for(int i=0; i < CHAR_COUNT; ++i) {
char_weights[i] += 1e-9; // Small epsilon to ensure non-zero weight if all P_i are zero for a char
total_weight += char_weights[i];
}
if (total_weight < 1e-8 && CHAR_COUNT > 0) { // All P_i were zero or very small
for(int i=0; i<CHAR_COUNT; ++i) char_weights[i] = 1.0/CHAR_COUNT; // Uniform
total_weight = 1.0;
}
std::array<double, CHAR_COUNT> cumulative_probs;
double current_cumulative = 0;
for(int i=0; i < CHAR_COUNT; ++i) {
if (total_weight > 1e-9) current_cumulative += char_weights[i] / total_weight;
else if (CHAR_COUNT > 0) current_cumulative += 1.0 / CHAR_COUNT; // Fallback if total_weight is still zero
cumulative_probs[i] = current_cumulative;
}
if (CHAR_COUNT > 0) cumulative_probs[CHAR_COUNT - 1] = 1.0000000001; // Ensure last bucket catches due to precision
for (int i = 0; i < M_FIXED; ++i) {
double r_val = rnd.next_double();
char assigned_char = (CHAR_COUNT > 0) ? ('a' + CHAR_COUNT - 1) : 'a'; // Default to last char if loop fails
if (CHAR_COUNT > 0) {
for (int char_code = 0; char_code < CHAR_COUNT; ++char_code) {
if (r_val < cumulative_probs[char_code]) {
assigned_char = 'a' + char_code;
break;
}
}
}
sol.C[i] = assigned_char;
}
}
void C_and_A_init_greedy_string_cycle(Solution& sol, Random& rnd, const ProblemInput& input, const GlobalPrecomputedData& precomputed) {
if (M_FIXED == 0) return;
int best_s_idx = -1;
int current_max_P = -1;
int current_min_len_for_max_P = MAX_S_LEN_FIXED + 5;
std::string current_best_S_lex_for_max_P = "~"; // Lexicographically large sentinel
for (int i = 0; i < N_FIXED; ++i) {
if (input.S[i].empty()) continue;
int current_S_len = static_cast<int>(input.S[i].length()); // Cast for comparison
if (input.P[i] > current_max_P) {
current_max_P = input.P[i];
current_min_len_for_max_P = current_S_len;
current_best_S_lex_for_max_P = input.S[i];
best_s_idx = i;
} else if (input.P[i] == current_max_P) {
if (current_S_len < current_min_len_for_max_P) {
current_min_len_for_max_P = current_S_len;
current_best_S_lex_for_max_P = input.S[i];
best_s_idx = i;
} else if (current_S_len == current_min_len_for_max_P) {
if (input.S[i] < current_best_S_lex_for_max_P) {
current_best_S_lex_for_max_P = input.S[i];
best_s_idx = i;
}
}
}
}
std::array<double, N_FIXED> dummy_qk;
std::fill(dummy_qk.begin(), dummy_qk.end(), 0.0);
if (best_s_idx != -1 && static_cast<int>(input.S[best_s_idx].length()) <= M_FIXED && !input.S[best_s_idx].empty()) {
const std::string& S_star = input.S[best_s_idx];
int s_star_len = S_star.length();
// s_star_len > 0 is guaranteed by !input.S[best_s_idx].empty()
C_init_weighted_random(sol, rnd, input, precomputed); // Initialize all C first
for (int i = 0; i < s_star_len; ++i) {
sol.C[i] = S_star[i]; // Overwrite C for cycle states
}
for (int i = 0; i < s_star_len; ++i) {
// sol.A[i] will be set by normalize_row_A
std::array<double, M_FIXED> W_temp;
std::fill(W_temp.begin(), W_temp.end(), 0.0);
int next_state_in_cycle = (i + 1) % s_star_len;
if (M_FIXED == 1 || s_star_len == M_FIXED) {
W_temp[next_state_in_cycle] = 100.0;
} else {
W_temp[next_state_in_cycle] = 95.0;
// Try to pick a random state for the remaining 5% that is NOT next_state_in_cycle
int other_target_state_idx = rnd.next_int_range(0, M_FIXED - 1);
if (other_target_state_idx == next_state_in_cycle) { // If same, pick another if possible
if (M_FIXED > 1) { // Need at least 2 states to pick a different one
other_target_state_idx = (next_state_in_cycle + 1 + rnd.next_int_range(0, M_FIXED - 2)) % M_FIXED;
}
// If M_FIXED=1 or still same after retry (M_FIXED=2, unlucky), then it's fine, W_temp will handle it.
}
W_temp[other_target_state_idx] += 5.0; // Add to existing (0.0) or could sum if other_target is next_state_in_cycle
}
normalize_row_A(sol.A[i], W_temp, rnd);
}
// For states NOT in the S_star cycle (i.e., s_star_len to M_FIXED-1), initialize their A rows
// Their C values are already set by C_init_weighted_random.
for (int i = s_star_len; i < M_FIXED; ++i) {
update_row_A_from_adaptive_heuristic(i, sol, input, rnd, dummy_qk, precomputed);
}
} else { // Fallback if no good S_star or S_star too long
C_init_weighted_random(sol, rnd, input, precomputed);
for (int i = 0; i < M_FIXED; ++i) {
update_row_A_from_adaptive_heuristic(i, sol, input, rnd, dummy_qk, precomputed);
}
}
}
void C_init_cyclic(Solution& sol, Random& /*rnd*/, const ProblemInput& /*input*/, const GlobalPrecomputedData& /*precomputed*/) {
if (M_FIXED == 0 || CHAR_COUNT == 0) {
if (M_FIXED > 0 && CHAR_COUNT==0) for(int i=0; i<M_FIXED; ++i) sol.C[i] = 'a';
return;
}
int states_per_char_bucket = std::max(1, M_FIXED / CHAR_COUNT);
for (int i = 0; i < M_FIXED; ++i) {
sol.C[i] = 'a' + ((i / states_per_char_bucket) % CHAR_COUNT) ;
}
}
void C_init_random(Solution& sol, Random& rnd, const ProblemInput& /*input*/, const GlobalPrecomputedData& /*precomputed*/) {
if (M_FIXED == 0 || CHAR_COUNT == 0) {
if (M_FIXED > 0 && CHAR_COUNT==0) for(int i=0; i<M_FIXED; ++i) sol.C[i] = 'a';
return;
}
for (int i = 0; i < M_FIXED; ++i) {
sol.C[i] = 'a' + rnd.next_int_range(0, CHAR_COUNT - 1);
}
}
void C_init_block(Solution& sol, Random& /*rnd*/, const ProblemInput& /*input*/, const GlobalPrecomputedData& /*precomputed*/) {
if (M_FIXED == 0 || CHAR_COUNT == 0) {
if (M_FIXED > 0 && CHAR_COUNT==0) for(int i=0; i<M_FIXED; ++i) sol.C[i] = 'a';
return;
}
for (int i = 0; i < M_FIXED; ++i) {
sol.C[i] = 'a' + (i % CHAR_COUNT);
}
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
Timer overall_timer_main;
unsigned int base_seed = static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count());
#ifdef ATCODER_DEBUG
// std::cerr << "DEBUG MODE: Using fixed seed." << std::endl;
base_seed = 0xC0FFEE; // A fixed seed for local debugging
#endif
ProblemInput input_data;
input_data.read();
GlobalPrecomputedData global_precomputed;
global_precomputed.precompute(input_data.S);
Solution overall_best_sol;
double overall_max_score = -std::numeric_limits<double>::infinity();
double total_time_limit_seconds = 1.98; // Slightly less than 2.0s for safety margin
std::vector<InitializerMeta> initializers_meta;
initializers_meta.push_back({InitializerType::C_AND_A, C_and_A_init_greedy_string_cycle, "GreedyCycleCandA"});
initializers_meta.push_back({InitializerType::C_ONLY, C_init_weighted_random, "WeightedRandomC"});
initializers_meta.push_back({InitializerType::C_ONLY, C_init_cyclic, "CyclicC"});
initializers_meta.push_back({InitializerType::C_ONLY, C_init_random, "RandomC"});
initializers_meta.push_back({InitializerType::C_ONLY, C_init_block, "BlockC"});
int num_restarts = initializers_meta.size();
bool first_solution_printed = false;
for (int run_idx = 0; run_idx < num_restarts; ++run_idx) {
Solution current_run_best_sol_storage;
double current_run_max_score = -std::numeric_limits<double>::infinity();
std::array<double, N_FIXED> current_run_best_Q_k_values;
Random rnd_for_run(base_seed + run_idx);
double elapsed_total_so_far = overall_timer_main.get_elapsed_seconds();
double remaining_total_time = total_time_limit_seconds - elapsed_total_so_far;
if (remaining_total_time < 0.01 && run_idx > 0) break;
remaining_total_time = std::max(0.005, remaining_total_time);
double time_for_this_sa_run = remaining_total_time / std::max(1, (num_restarts - run_idx));
const auto& current_initializer_meta = initializers_meta[run_idx];
solve(input_data, global_precomputed,
current_run_best_sol_storage, current_run_max_score, current_run_best_Q_k_values,
rnd_for_run, overall_timer_main,
time_for_this_sa_run, current_initializer_meta);
if (current_run_max_score > overall_max_score) {
overall_max_score = current_run_max_score;
overall_best_sol = current_run_best_sol_storage;
overall_best_sol.print();
std::cout.flush(); // Ensure it's printed immediately
#ifdef ATCODER_DEBUG
std::cerr << "New best score after run " << run_idx << " (" << initializers_meta[run_idx].name << "): " << std::round(overall_max_score) << " at time " << overall_timer_main.get_elapsed_seconds() << "s" << std::endl;
#endif
first_solution_printed = true;
}
}
if (!first_solution_printed) {
Solution default_sol; // Handles M_FIXED=0 or M_FIXED > 0 appropriately
default_sol.print();
std::cout.flush();
#ifdef ATCODER_DEBUG
std::cerr << "Printed default solution as no improvement was found." << std::endl;
#endif
}
#ifdef ATCODER_DEBUG
std::cerr << "Final best score: " << std::round(overall_max_score) << std::endl;
std::cerr << "Total execution time: " << overall_timer_main.get_elapsed_seconds() << "s" << std::endl;
#endif
return 0;
}
提出情報
コンパイルエラー
Main.cpp: In function ‘void normalize_row_A(std::array<int, 12>&, const std::array<double, 12>&, Random&)’:
Main.cpp:354:67: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
354 | if (p_indices.empty() || sh_i >= p_indices.size() -1 && sh_i != 0) break; // Avoid issue if size is 0 or 1
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
Main.cpp: In function ‘void solve(const ProblemInput&, const GlobalPrecomputedData&, Solution&, double&, std::array<double, 36>&, Random&, const Timer&, double, const InitializerMeta&)’:
Main.cpp:525:100: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
525 | if (predecessors_to_update.empty() || sh_i >= predecessors_to_update.size() -1 && sh_i != 0) break;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
Main.cpp:562:100: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
562 | if (predecessors_to_update.empty() || sh_i >= predecessors_to_update.size() -1 && sh_i != 0) break;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
ジャッジ結果
| セット名 |
test_ALL |
| 得点 / 配点 |
6233412 / 150000000 |
| 結果 |
|
| セット名 |
テストケース |
| 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 |
1981 ms |
4048 KiB |
| test_0001.txt |
AC |
1981 ms |
4004 KiB |
| test_0002.txt |
AC |
1981 ms |
4040 KiB |
| test_0003.txt |
AC |
1981 ms |
3884 KiB |
| test_0004.txt |
AC |
1981 ms |
3860 KiB |
| test_0005.txt |
AC |
1981 ms |
3884 KiB |
| test_0006.txt |
AC |
1981 ms |
4040 KiB |
| test_0007.txt |
AC |
1981 ms |
4060 KiB |
| test_0008.txt |
AC |
1981 ms |
3892 KiB |
| test_0009.txt |
AC |
1981 ms |
4000 KiB |
| test_0010.txt |
AC |
1981 ms |
3900 KiB |
| test_0011.txt |
AC |
1981 ms |
3936 KiB |
| test_0012.txt |
AC |
1981 ms |
4052 KiB |
| test_0013.txt |
AC |
1981 ms |
4004 KiB |
| test_0014.txt |
AC |
1981 ms |
4012 KiB |
| test_0015.txt |
AC |
1981 ms |
3896 KiB |
| test_0016.txt |
AC |
1981 ms |
3944 KiB |
| test_0017.txt |
AC |
1981 ms |
4048 KiB |
| test_0018.txt |
AC |
1981 ms |
3940 KiB |
| test_0019.txt |
AC |
1981 ms |
4056 KiB |
| test_0020.txt |
AC |
1981 ms |
4008 KiB |
| test_0021.txt |
AC |
1981 ms |
3888 KiB |
| test_0022.txt |
AC |
1981 ms |
4016 KiB |
| test_0023.txt |
AC |
1981 ms |
4008 KiB |
| test_0024.txt |
AC |
1981 ms |
3888 KiB |
| test_0025.txt |
AC |
1981 ms |
4012 KiB |
| test_0026.txt |
AC |
1981 ms |
3944 KiB |
| test_0027.txt |
AC |
1981 ms |
4004 KiB |
| test_0028.txt |
AC |
1981 ms |
4004 KiB |
| test_0029.txt |
AC |
1981 ms |
4048 KiB |
| test_0030.txt |
AC |
1981 ms |
4016 KiB |
| test_0031.txt |
AC |
1981 ms |
4008 KiB |
| test_0032.txt |
AC |
1981 ms |
4048 KiB |
| test_0033.txt |
AC |
1981 ms |
4060 KiB |
| test_0034.txt |
AC |
1981 ms |
3896 KiB |
| test_0035.txt |
AC |
1981 ms |
3888 KiB |
| test_0036.txt |
AC |
1981 ms |
4040 KiB |
| test_0037.txt |
AC |
1981 ms |
3896 KiB |
| test_0038.txt |
AC |
1981 ms |
3940 KiB |
| test_0039.txt |
AC |
1981 ms |
3888 KiB |
| test_0040.txt |
AC |
1981 ms |
3908 KiB |
| test_0041.txt |
AC |
1981 ms |
3944 KiB |
| test_0042.txt |
AC |
1981 ms |
4016 KiB |
| test_0043.txt |
AC |
1981 ms |
3944 KiB |
| test_0044.txt |
AC |
1981 ms |
4000 KiB |
| test_0045.txt |
AC |
1981 ms |
3888 KiB |
| test_0046.txt |
AC |
1981 ms |
4004 KiB |
| test_0047.txt |
AC |
1981 ms |
3944 KiB |
| test_0048.txt |
AC |
1981 ms |
3884 KiB |
| test_0049.txt |
AC |
1981 ms |
3892 KiB |
| test_0050.txt |
AC |
1981 ms |
3948 KiB |
| test_0051.txt |
AC |
1981 ms |
4008 KiB |
| test_0052.txt |
AC |
1981 ms |
4012 KiB |
| test_0053.txt |
AC |
1981 ms |
4004 KiB |
| test_0054.txt |
AC |
1981 ms |
4004 KiB |
| test_0055.txt |
AC |
1981 ms |
3896 KiB |
| test_0056.txt |
AC |
1981 ms |
4008 KiB |
| test_0057.txt |
AC |
1981 ms |
4060 KiB |
| test_0058.txt |
AC |
1981 ms |
4056 KiB |
| test_0059.txt |
AC |
1981 ms |
4012 KiB |
| test_0060.txt |
AC |
1981 ms |
3892 KiB |
| test_0061.txt |
AC |
1981 ms |
4012 KiB |
| test_0062.txt |
AC |
1981 ms |
3896 KiB |
| test_0063.txt |
AC |
1981 ms |
3944 KiB |
| test_0064.txt |
AC |
1981 ms |
4008 KiB |
| test_0065.txt |
AC |
1981 ms |
4056 KiB |
| test_0066.txt |
AC |
1981 ms |
3904 KiB |
| test_0067.txt |
AC |
1981 ms |
4056 KiB |
| test_0068.txt |
AC |
1981 ms |
4060 KiB |
| test_0069.txt |
AC |
1981 ms |
3944 KiB |
| test_0070.txt |
AC |
1981 ms |
4048 KiB |
| test_0071.txt |
AC |
1981 ms |
4016 KiB |
| test_0072.txt |
AC |
1981 ms |
3936 KiB |
| test_0073.txt |
AC |
1981 ms |
4068 KiB |
| test_0074.txt |
AC |
1981 ms |
3864 KiB |
| test_0075.txt |
AC |
1981 ms |
4008 KiB |
| test_0076.txt |
AC |
1981 ms |
4060 KiB |
| test_0077.txt |
AC |
1981 ms |
4012 KiB |
| test_0078.txt |
AC |
1981 ms |
4012 KiB |
| test_0079.txt |
AC |
1981 ms |
4004 KiB |
| test_0080.txt |
AC |
1981 ms |
4052 KiB |
| test_0081.txt |
AC |
1981 ms |
4044 KiB |
| test_0082.txt |
AC |
1981 ms |
4004 KiB |
| test_0083.txt |
AC |
1981 ms |
4024 KiB |
| test_0084.txt |
AC |
1981 ms |
4012 KiB |
| test_0085.txt |
AC |
1981 ms |
4004 KiB |
| test_0086.txt |
AC |
1981 ms |
4004 KiB |
| test_0087.txt |
AC |
1981 ms |
4032 KiB |
| test_0088.txt |
AC |
1981 ms |
4016 KiB |
| test_0089.txt |
AC |
1981 ms |
4056 KiB |
| test_0090.txt |
AC |
1981 ms |
3948 KiB |
| test_0091.txt |
AC |
1981 ms |
3888 KiB |
| test_0092.txt |
AC |
1981 ms |
3940 KiB |
| test_0093.txt |
AC |
1981 ms |
3940 KiB |
| test_0094.txt |
AC |
1981 ms |
3940 KiB |
| test_0095.txt |
AC |
1981 ms |
4012 KiB |
| test_0096.txt |
AC |
1981 ms |
3892 KiB |
| test_0097.txt |
AC |
1981 ms |
4052 KiB |
| test_0098.txt |
AC |
1981 ms |
3936 KiB |
| test_0099.txt |
AC |
1981 ms |
4052 KiB |
| test_0100.txt |
AC |
1981 ms |
3940 KiB |
| test_0101.txt |
AC |
1981 ms |
3864 KiB |
| test_0102.txt |
AC |
1981 ms |
3884 KiB |
| test_0103.txt |
AC |
1981 ms |
4040 KiB |
| test_0104.txt |
AC |
1981 ms |
3968 KiB |
| test_0105.txt |
AC |
1981 ms |
4004 KiB |
| test_0106.txt |
AC |
1981 ms |
3884 KiB |
| test_0107.txt |
AC |
1981 ms |
4012 KiB |
| test_0108.txt |
AC |
1981 ms |
4048 KiB |
| test_0109.txt |
AC |
1981 ms |
4012 KiB |
| test_0110.txt |
AC |
1981 ms |
4056 KiB |
| test_0111.txt |
AC |
1981 ms |
4004 KiB |
| test_0112.txt |
AC |
1981 ms |
4008 KiB |
| test_0113.txt |
AC |
1981 ms |
4040 KiB |
| test_0114.txt |
AC |
1981 ms |
4008 KiB |
| test_0115.txt |
AC |
1981 ms |
4052 KiB |
| test_0116.txt |
AC |
1981 ms |
4048 KiB |
| test_0117.txt |
AC |
1981 ms |
3940 KiB |
| test_0118.txt |
AC |
1981 ms |
3872 KiB |
| test_0119.txt |
AC |
1981 ms |
3952 KiB |
| test_0120.txt |
AC |
1981 ms |
4008 KiB |
| test_0121.txt |
AC |
1981 ms |
4060 KiB |
| test_0122.txt |
AC |
1981 ms |
4064 KiB |
| test_0123.txt |
AC |
1981 ms |
4064 KiB |
| test_0124.txt |
AC |
1981 ms |
4032 KiB |
| test_0125.txt |
AC |
1981 ms |
3944 KiB |
| test_0126.txt |
AC |
1981 ms |
4016 KiB |
| test_0127.txt |
AC |
1981 ms |
4052 KiB |
| test_0128.txt |
AC |
1981 ms |
4040 KiB |
| test_0129.txt |
AC |
1981 ms |
4016 KiB |
| test_0130.txt |
AC |
1981 ms |
4004 KiB |
| test_0131.txt |
AC |
1981 ms |
3980 KiB |
| test_0132.txt |
AC |
1981 ms |
3880 KiB |
| test_0133.txt |
AC |
1981 ms |
4048 KiB |
| test_0134.txt |
AC |
1981 ms |
3884 KiB |
| test_0135.txt |
AC |
1981 ms |
3888 KiB |
| test_0136.txt |
AC |
1981 ms |
3884 KiB |
| test_0137.txt |
AC |
1981 ms |
4056 KiB |
| test_0138.txt |
AC |
1981 ms |
4060 KiB |
| test_0139.txt |
AC |
1981 ms |
3944 KiB |
| test_0140.txt |
AC |
1981 ms |
4008 KiB |
| test_0141.txt |
AC |
1981 ms |
3952 KiB |
| test_0142.txt |
AC |
1981 ms |
3984 KiB |
| test_0143.txt |
AC |
1981 ms |
3884 KiB |
| test_0144.txt |
AC |
1981 ms |
3904 KiB |
| test_0145.txt |
AC |
1981 ms |
4008 KiB |
| test_0146.txt |
AC |
1981 ms |
4044 KiB |
| test_0147.txt |
AC |
1981 ms |
3948 KiB |
| test_0148.txt |
AC |
1981 ms |
4012 KiB |
| test_0149.txt |
AC |
1981 ms |
4052 KiB |