結果
問題 |
No.2860 Heal Slimes
|
ユーザー |
|
提出日時 | 2025-04-18 16:03:38 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 4,823 bytes |
コンパイル時間 | 801 ms |
コンパイル使用メモリ | 73,116 KB |
実行使用メモリ | 7,848 KB |
最終ジャッジ日時 | 2025-04-18 16:03:42 |
合計ジャッジ時間 | 3,452 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 25 WA * 35 |
ソースコード
#include <iostream> #include <vector> #include <numeric> // 標準ライブラリインクルード(今回は直接は使わない) // 負の数も扱えるように剰余を計算する関数 (modulus > 0 を想定) // C++の % 演算子は結果が負になることがあるため、常に 0 以上 modulus 未満の値を返すように調整します。 long long correct_modulo(long long value, long long modulus) { long long result = value % modulus; // 結果が負の場合は、modulus を足して非負にする return result < 0 ? result + modulus : result; } int main() { // 標準入出力の高速化 std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); long long n; // スライムの数 long long k; // 回復魔法の対象となる連続するスライムの数 long long x; // 回復量 std::cin >> n >> k >> x; std::vector<long long> h(n); // 各スライムの体力 for (int i = 0; i < n; ++i) { std::cin >> h[i]; } // --- 条件1: 全てのスライムの体力が X で割った余りが等しいか --- // 回復魔法は体力を X ずつ増やす操作です。 // 最終的に全てのスライムの体力を等しくするためには、 // どのスライムの体力も X で割った余りが同じでなければなりません。 // なぜなら、操作によって体力は X の倍数だけ変化するため、 // X で割った余りは変化しないからです。 // したがって、初期状態で全ての H_i mod X が等しい必要があります。 long long h0_mod = correct_modulo(h[0], x); // 最初のスライムの体力の余りを基準とする for (int i = 1; i < n; ++i) { if (correct_modulo(h[i], x) != h0_mod) { // 一つでも余りが異なれば、目標達成は不可能 std::cout << "No" << std::endl; return 0; } } // --- 条件2: 差分に基づく累積和のチェック --- // スライム i と i-1 の体力の差を D_i = H_i - H_{i-1} (i >= 1) とします。 // 全てのスライムの体力を等しくするということは、最終的に全ての D_i (i >= 1) を 0 にするということです。 // 回復魔法を j 番目から j+K-1 番目のスライムにかける操作は、 // D_j を X 増加させ、D_{j+K} を X 減少させる効果があります (ただし j+K < N)。 // (j=0 の場合は D_0 を X 増加させ、D_K を X 減少させます) // // 条件1より、全ての D_i (i >= 1) は X で割り切れることが保証されています。 // そこで、q_i = D_i / X とします。 // 操作は、q_j に +1 し、q_{j+K} に -1 する (j >= 1)、 // または D_0 に +X し、q_K に -1 する (j = 0) と言い換えられます。 // // j >= 1 の操作は、インデックスを K で割った余りが同じペア (j と j+K) の間で値 (+1 と -1) を移動させるだけです。 // このため、インデックス i を K で割った余りが m (ただし m = 1, 2, ..., K-1) であるような q_i の合計値は、 // j >= 1 の操作によっては変化しません。 // 最終目標 (全ての q_i = 0, i >= 1) では、これらの合計値は当然 0 です。 // したがって、初期状態においても、これらのグループ (m=1 から K-1) の q_i の合計値が 0 でなければなりません。 // // グループ m = 0 (インデックス K, 2K, ...) の合計値は、j=0 の操作 (D_0 と q_K に影響) を使うことで // 任意の値に変更可能なので、初期値が 0 である必要はありません。 // 各グループ (mod K) ごとの q_i の合計値を計算します。 std::vector<long long> sums(k, 0LL); // sums[m] は i % k == m となる q_i の合計を保持 (long long で初期化) for (int i = 1; i < n; ++i) { // D_i = H[i] - H[i-1] // q_i = D_i / x (条件1から割り切れることが保証されている) long long qi = (h[i] - h[i - 1]) / x; // q_i を、対応するグループ (インデックス i を K で割った余り) の合計に加算します。 sums[i % k] += qi; } // グループ m = 1 から K-1 の合計値が 0 かどうかをチェックします。 for (int m = 1; m < k; ++m) { if (sums[m] != 0) { // 合計が 0 でないグループが一つでもあれば、目標達成は不可能 std::cout << "No" << std::endl; return 0; } } // 上記の条件1と条件2を両方満たす場合、全てのスライムの体力を等しくすることが可能です。 std::cout << "Yes" << std::endl; return 0; }