結果
| 問題 |
No.2891 Mint
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-09-13 23:16:18 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 1,514 bytes |
| コンパイル時間 | 2,383 ms |
| コンパイル使用メモリ | 90,812 KB |
| 実行使用メモリ | 10,752 KB |
| 最終ジャッジ日時 | 2024-09-13 23:16:32 |
| 合計ジャッジ時間 | 5,629 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 1 TLE * 1 -- * 52 |
ソースコード
#include <iostream>
#include <vector>
#include <atcoder/modint>
using namespace std;
using ll = long long;
using mint = atcoder::static_modint<998244353>;
int main () {
ll N, M; cin >> N >> M;
// modが変化したときの結果の変化は必ずしもめちゃくちゃというわけではない。
// 法mをM / mの値で分ける。
// mとm + 1が同じグループに入っているとする。この時、(M % m) = (M % m) + (M / m)が成立。
// 一つのグループの総和計算は等差数列計算で出来る。
// 後はなんかいい感じになるんじゃないですかね(適当)
mint ans = 0;
// 0で分類されるグループについての総和をとりますよっと
ans += mint(max(N - M, 0LL)) * M;
N = min(N, M);
auto f = [&] (mint a, mint r, mint n) {
mint res = 0;
res += a * n;
res += ((n - 1) * n / 2) * r;
return res;
};
int y = 1;
ll up = 0;
while (true) {
// あるグループがすべて属する閉区間を数学で求めます。
ll l = M / (y + 1) + 1;
ll r = min(M / y, N);
ll len = r - l + 1;
if (len <= 0) continue;
if (len == 1) {
up = l;
break;
}
// rでの値(初項)を求める。
ll fi = M % r;
ans += f(fi, y, len);
y++;
}
for (int m = 1; m <= up; m++) {
ans += M % m;
}
cout << ans.val() << "\n";
return 0;
}