結果
| 問題 | No.3496 協力カード当て |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-04-07 15:29:31 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,197 bytes |
| 記録 | |
| コンパイル時間 | 5,877 ms |
| コンパイル使用メモリ | 193,180 KB |
| 実行使用メモリ | 30,320 KB |
| スコア | 0 |
| 平均クエリ数 | 40.00 |
| 最終ジャッジ日時 | 2026-04-14 23:48:15 |
| 合計ジャッジ時間 | 14,611 ms |
|
ジャッジサーバーID (参考情報) |
judge1_0 / judge3_1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | WA * 16 |
ソースコード
/**
* コミュニケーション問題 ファイル経由通信ハックテスト
*
* ファイル経由で相手の手札を不正に取得し、正解を出す。
* AC → セキュリティホール!
* WA → ファイル通信は正しくブロックされている
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <unistd.h>
#include <map>
using namespace std;
void try_write(const char* path, const string& data) {
FILE* f = fopen(path, "w");
if (f) {
fprintf(f, "%s", data.c_str());
fclose(f);
fprintf(stderr, "[INFO] write ok: %s\n", path);
} else {
fprintf(stderr, "[INFO] write fail: %s\n", path);
}
}
bool try_read(const char* path, string& out) {
FILE* f = fopen(path, "r");
if (!f) return false;
char buf[4096];
if (fgets(buf, sizeof(buf), f)) { out = buf; fclose(f); return true; }
fclose(f);
return false;
}
int main() {
int id, N, M;
scanf("%d %d %d", &id, &N, &M);
vector<int> hand(N);
map<int,int> my_count;
for (int i = 0; i < N; i++) {
scanf("%d", &hand[i]);
my_count[hand[i]]++;
}
// 自分の手札を文字列化
string hand_str;
for (int i = 0; i < N; i++) {
if (i > 0) hand_str += " ";
hand_str += to_string(hand[i]);
}
// 複数パスでファイル書き込みを試みる
const char* bases[] = {
"/tmp/hack", "/dev/shm/hack", "/var/tmp/hack",
"/home/judge/hack", "/home/judge1/hack",
};
for (auto base : bases) {
char path[256];
snprintf(path, sizeof(path), "%s_%d", base, id);
try_write(path, hand_str);
}
// 相手が書くのを待つ
usleep(500000);
// 相手の手札を読み取り
int other_id = 3 - id;
vector<int> opp_hand;
map<int,int> opp_count;
bool hacked = false;
for (auto base : bases) {
char path[256];
snprintf(path, sizeof(path), "%s_%d", base, other_id);
string data;
if (try_read(path, data)) {
istringstream iss(data);
int v;
opp_hand.clear();
opp_count.clear();
while (iss >> v) { opp_hand.push_back(v); opp_count[v]++; }
if ((int)opp_hand.size() == N) {
hacked = true;
fprintf(stderr, "[HACK] Read opponent hand from %s_%d\n", base, other_id);
break;
}
}
}
// 全値のCOUNTを集める(質問は必要)
map<int,int> total;
int asked = 0;
char cmd[16];
while (scanf("%s", cmd) == 1) {
if (strcmp(cmd, "END") == 0) { int q; scanf("%d", &q); break; }
if (strcmp(cmd, "TURN") == 0) {
if (asked < M) {
asked++;
printf("ASK %d\n", asked);
fflush(stdout);
} else {
// GUESS
if (hacked) {
// ファイルから相手の手札を知っているので正解可能
vector<int> guess;
for (int v = 1; v <= M; v++) {
int t = total.count(v) ? total[v] : 0;
int c = t - my_count[v] - opp_count[v];
for (int j = 0; j < c; j++) guess.push_back(v);
}
sort(guess.begin(), guess.end());
printf("GUESS");
for (int v : guess) printf(" %d", v);
printf("\n");
} else {
// ハック失敗 → 当てずっぽう
printf("GUESS");
for (int i = 0; i < N; i++) printf(" 1");
printf("\n");
}
fflush(stdout);
}
} else if (strcmp(cmd, "WAIT") == 0) {
// nothing
} else if (strcmp(cmd, "COUNT") == 0) {
int x, k; scanf("%d %d", &x, &k);
total[x] = k;
} else if (strcmp(cmd, "GUESSED") == 0) {
int g, ok; scanf("%d %d", &g, &ok);
}
}
return 0;
}