結果
| 問題 | No.3506 All Distance is Square Number |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-04-18 07:15:41 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 6,521 bytes |
| 記録 | |
| コンパイル時間 | 2,104 ms |
| コンパイル使用メモリ | 240,984 KB |
| 実行使用メモリ | 7,972 KB |
| 最終ジャッジ日時 | 2026-04-18 07:16:13 |
| 合計ジャッジ時間 | 10,836 ms |
|
ジャッジサーバーID (参考情報) |
judge1_1 / judge2_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 10 TLE * 1 -- * 18 |
ソースコード
#pragma GCC optimize("O3,unroll-loops")
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
#include <random>
using namespace std;
int N;
int W_edge[105];
vector<int> unused_even;
int adj_to[105][5];
int adj_weight[105][5];
int adj_id[105][5];
int adj_deg[105];
bool is_sq[40005];
void build_adj() {
for(int i=1; i<=N; ++i) adj_deg[i] = 0;
for(int i=1; i<N; ++i) {
adj_to[i][adj_deg[i]] = i+1; adj_weight[i][adj_deg[i]] = 2*i-1; adj_id[i][adj_deg[i]] = i; adj_deg[i]++;
adj_to[i+1][adj_deg[i+1]] = i; adj_weight[i+1][adj_deg[i+1]] = 2*i-1; adj_id[i+1][adj_deg[i+1]] = i; adj_deg[i+1]++;
}
for(int k=1; k<=N-2; ++k) {
adj_to[k][adj_deg[k]] = k+2; adj_weight[k][adj_deg[k]] = W_edge[k]; adj_id[k][adj_deg[k]] = N-1+k; adj_deg[k]++;
adj_to[k+2][adj_deg[k+2]] = k; adj_weight[k+2][adj_deg[k+2]] = W_edge[k]; adj_id[k+2][adj_deg[k+2]] = N-1+k; adj_deg[k+2]++;
}
}
int evaluate_graph() {
int missing = 0;
static int q_u[4005];
static int q_sum[4005];
static unsigned __int128 q_vis[4005];
for (int i = 1; i < N; ++i) {
int needed = N - i;
int found = 0;
bool ok[105] = {false};
int head = 0, tail = 0;
q_u[tail] = i; q_sum[tail] = 0; q_vis[tail] = ((unsigned __int128)1 << i); tail++;
while(head < tail && head < 1500 && found < needed) {
int u = q_u[head];
int sum = q_sum[head];
unsigned __int128 vmask = q_vis[head];
head++;
if (u > i && sum > 0 && is_sq[sum] && !ok[u]) {
ok[u] = true;
found++;
if (found == needed) break;
}
for(int k = 0; k < adj_deg[u]; ++k) {
int v = adj_to[u][k];
if (!((vmask >> v) & 1)) {
int nsum = sum + adj_weight[u][k];
if (nsum < 40005 && tail < 4000) {
q_u[tail] = v; q_sum[tail] = nsum; q_vis[tail] = vmask | ((unsigned __int128)1 << v); tail++;
}
}
}
}
missing += (needed - found);
}
return missing;
}
struct QState { int u; int sum; unsigned __int128 vis; short path[105]; short len; };
QState q_out[30005];
vector<int> solve_path(int start, int target) {
int head = 0, tail = 0;
q_out[tail].u = start; q_out[tail].sum = 0; q_out[tail].vis = ((unsigned __int128)1 << start); q_out[tail].len = 0; tail++;
while(head < tail) {
QState curr = q_out[head++];
if (curr.u == target && curr.sum > 0 && is_sq[curr.sum]) {
vector<int> res;
for(int i=0; i<curr.len; ++i) res.push_back(curr.path[i]);
return res;
}
for(int k=0; k<adj_deg[curr.u]; ++k) {
int v = adj_to[curr.u][k];
if (!((curr.vis >> v) & 1)) {
int nsum = curr.sum + adj_weight[curr.u][k];
if (nsum < 40005 && tail < 30000) {
q_out[tail].u = v; q_out[tail].sum = nsum; q_out[tail].vis = curr.vis | ((unsigned __int128)1 << v);
for(int p=0; p<curr.len; ++p) q_out[tail].path[p] = curr.path[p];
q_out[tail].path[curr.len] = adj_id[curr.u][k]; q_out[tail].len = curr.len + 1; tail++;
}
}
}
}
return {};
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
if (!(cin >> N)) return 0;
for (int i = 0; i < 40005; ++i) is_sq[i] = false;
for (int i = 1; i * i < 40005; ++i) is_sq[i * i] = true;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int odd_squares[] = {9, 25, 49, 81, 121, 169, 225, 289, 361};
bool used_init[205] = {false};
for(int k=1; k<=N-2; ++k) {
vector<int> magics;
for(int s : odd_squares) {
int w = s - (2*k - 1);
if(w >= 2 && w <= 200 && w % 2 == 0 && !used_init[w]) magics.push_back(w);
}
if(!magics.empty()) {
int chosen = magics[rng() % magics.size()];
W_edge[k] = chosen;
used_init[chosen] = true;
} else {
W_edge[k] = 0;
}
}
for(int i=2; i<=200; i+=2) {
if(!used_init[i]) unused_even.push_back(i);
}
shuffle(unused_even.begin(), unused_even.end(), rng);
for(int k=1; k<=N-2; ++k) {
if(W_edge[k] == 0) {
W_edge[k] = unused_even.back(); unused_even.pop_back();
}
}
build_adj();
int best_score = evaluate_graph();
int no_improve = 0;
while (best_score > 0) {
int r1 = rng() % (N - 2) + 1;
int type = rng() % 2;
int old_w1 = W_edge[r1];
if (type == 0 && !unused_even.empty()) {
int idx = rng() % unused_even.size();
int old_w2 = unused_even[idx];
W_edge[r1] = old_w2;
build_adj();
int new_score = evaluate_graph();
if (new_score <= best_score) {
best_score = new_score; unused_even[idx] = old_w1; no_improve = 0;
} else {
W_edge[r1] = old_w1; build_adj(); no_improve++;
}
} else {
int r2 = rng() % (N - 2) + 1;
if (r1 == r2) continue;
swap(W_edge[r1], W_edge[r2]);
build_adj();
int new_score = evaluate_graph();
if (new_score <= best_score) {
best_score = new_score; no_improve = 0;
} else {
swap(W_edge[r1], W_edge[r2]); build_adj(); no_improve++;
}
}
if (no_improve > 300) {
for(int step=0; step<3; ++step) {
int a = rng() % (N - 2) + 1;
int b = rng() % (N - 2) + 1;
swap(W_edge[a], W_edge[b]);
}
build_adj();
best_score = evaluate_graph();
no_improve = 0;
}
}
cout << (2 * N - 3) << "\n";
for (int i = 1; i < N; ++i) cout << i << " " << (i + 1) << " " << (2 * i - 1) << "\n";
for (int k = 1; k <= N - 2; ++k) cout << k << " " << (k + 2) << " " << W_edge[k] << "\n";
for (int i = 1; i <= N; ++i) {
for (int j = i + 1; j <= N; ++j) {
vector<int> path = solve_path(i, j);
cout << path.size() << "\n";
for (int k = 0; k < path.size(); ++k) {
cout << path[k] << (k == path.size() - 1 ? "" : " ");
}
cout << "\n";
}
}
return 0;
}