結果
問題 |
No.2860 Heal Slimes
|
ユーザー |
|
提出日時 | 2025-04-18 16:27:30 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 34 ms / 2,000 ms |
コード長 | 4,163 bytes |
コンパイル時間 | 1,975 ms |
コンパイル使用メモリ | 198,444 KB |
実行使用メモリ | 9,472 KB |
最終ジャッジ日時 | 2025-04-18 16:27:37 |
合計ジャッジ時間 | 6,096 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 60 |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; // o4-mini-high int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int N, K; ll X; cin >> N >> K >> X; vector<ll> H(N); for (int i = 0; i < N; i++) { cin >> H[i]; } // K==N の特別扱い if (K == N) { bool all_eq = true; for (int i = 1; i < N; i++) { if (H[i] != H[0]) { all_eq = false; break; } } cout << (all_eq ? "Yes\n" : "No\n"); continue; } // まず mod X が揃っているか ll r = H[0] % X; bool ok = true; for (int i = 1; i < N; i++) { if (H[i] % X != r) { ok = false; break; } } if (!ok) { cout << "No\n"; continue; } // H[i] = X*a[i] + r に正規化 vector<ll> a(N+1); for (int i = 1; i <= N; i++) { a[i] = (H[i-1] - r) / X; } // 差分 d[i] = a[i] - a[i-1] vector<ll> d(N+2); for (int i = 2; i <= N; i++) { d[i] = a[i] - a[i-1]; } // d[N+1] は使わないが念のため d[N+1] = -a[N]; int M = N - K + 1; // op の C に依らないベース値を再帰的に求める vector<ll> base_op(M+2); base_op[1] = -a[1]; for (int j = 2; j <= M; j++) { if (j <= K) { base_op[j] = -d[j]; } else { base_op[j] = -d[j] + base_op[j - K]; } } // 非負条件(Cに依らない op[j] >= 0) for (int j = 1; j <= M; j++) { if ((j - 1) % K != 0 && base_op[j] < 0) { ok = false; break; } } if (!ok) { cout << "No\n"; continue; } // ここで足りていなかった追加チェック: // i = M+1 .. K の間、差分方程式は 0 - 0 = -d[i] を強いる if (M + 1 <= K) { for (int i = M + 1; i <= K; i++) { if (d[i] != 0) { ok = false; break; } } if (!ok) { cout << "No\n"; continue; } } // C の下限を集める ll C_min = LLONG_MIN; for (int j = 1; j <= M; j++) { if ((j - 1) % K == 0) { C_min = max(C_min, -base_op[j]); } } // 末尾の整合性から C が一意に定まるか調べる int j_low = max(1, N - 2 * K + 2); int j_high = N - K; bool C_assigned = false; ll C_val = 0; for (int j = j_low; j <= j_high; j++) { int i = j + K; if ((j - 1) % K == 0) { ll needed = d[i] - base_op[j]; if (!C_assigned) { C_assigned = true; C_val = needed; } else if (C_val != needed) { ok = false; break; } } else { if (base_op[j] != d[i]) { ok = false; break; } } } if (!ok) { cout << "No\n"; continue; } // 最終ターゲット C は現在の最大 a[i] 以上でなければならない ll max_a = 0; for (int i = 1; i <= N; i++) { max_a = max(max_a, a[i]); } if (C_assigned) { // 一意に定まった C_val が条件を満たすか if (C_val < max_a || C_val < C_min) { cout << "No\n"; } else { cout << "Yes\n"; } } else { // 自由に C を選べるなら max(max_a, C_min) を取れば OK cout << "Yes\n"; } } return 0; }