結果
| 問題 |
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;
}