結果
| 問題 |
No.3118 Increment or Multiply
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-11-19 09:19:44 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 31 ms / 2,000 ms |
| コード長 | 2,442 bytes |
| コンパイル時間 | 717 ms |
| コンパイル使用メモリ | 80,048 KB |
| 実行使用メモリ | 7,716 KB |
| 最終ジャッジ日時 | 2025-11-19 11:11:15 |
| 合計ジャッジ時間 | 2,793 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 35 |
ソースコード
/**
* 問題: C=K から C=N にするための最小操作回数の総和
* 操作: +1 または *A
* * 解法:
* 逆から考える再帰構造を利用します。
* M = floor(N / A) とすると、
* 1. K > M の場合: A倍するとNを超えるため、+1のみで到達するしかない。
* コストは N - K。
* 2. K <= M の場合: Mまで到達してからA倍し、残りを+1するのが最適。
* コストは f(K, M) + 1 + (N % A)。
* * これにより、S(N) = S(M) + M*(1 + N%A) + (M+1からNまでの単純和) となる。
* 計算量は O(log N)。
* gemini 3-pro
*/
#include <iostream>
using namespace std;
long long MOD = 998244353;
long long INV2 = 499122177; // 2の逆元 (mod 998244353)
// 0 から k-1 までの総和 k*(k-1)/2 を mod で計算
long long sum_0_to_k_minus_1(long long k) {
if (k <= 0) return 0;
long long term1 = k % MOD;
long long term2 = (k - 1) % MOD;
long long res = term1 * term2 % MOD;
return res * INV2 % MOD;
}
long long solve(long long n, long long a) {
if (n == 0) return 0;
// A=1の場合は掛け算の意味がないため、全て+1で到達するしかない
// K=1..N それぞれについて N-K 回の操作
// 総和は sum_{i=1}^{N} (N-i) = sum_{j=0}^{N-1} j = N(N-1)/2
if (a == 1) {
return sum_0_to_k_minus_1(n);
}
// A > N の場合、一度も掛け算できないので A=1 と同じ扱い
if (n < a) {
return sum_0_to_k_minus_1(n);
}
long long m = n / a;
long long rem = n % a;
// 1. K > M の部分 (掛け算なし)
// 区間の長さは N - M
// コストの総和は 0 + 1 + ... + (N - M - 1)
long long part1 = sum_0_to_k_minus_1(n - m);
// 2. K <= M の部分 (再帰 + 追加コスト)
// S(M)
long long recursive_part = solve(m, a);
// 各要素に加算される定数コスト: 1 (掛け算) + rem (あまりの足し算)
long long constant_cost = (1 + rem) % MOD;
// これが M 個分ある
long long part2_constant = (m % MOD) * constant_cost % MOD;
long long total = (part1 + recursive_part + part2_constant) % MOD;
return total;
}
void solve_case() {
long long N, A;
cin >> N >> A;
cout << solve(N, A) << "\n";
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int T;
cin >> T;
while (T--) {
solve_case();
}
return 0;
}