実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 970
問題概要
正整数 に対して、
を
個つなげた整数を
とする。
を
で割った余りを出力せよ。
制約
は整数。
考察
を
回もつなげた数を扱えるわけもないので、何か工夫が必要。ここで、
の桁数を
として、いったん
を式で表してみると、
のように、等比数列の和の形になる。
これを すると、積はそのまま積の形で良いが、商については逆元をとるという、少々特殊な方法を取らなければならない。詳しくはこちらの記事を参照のこと。
式で表すとこんな感じ。 は、
における
の逆元を表している。
演算における累乗や逆元の計算は実装が少々面倒くさいが、それを解決するのが AC Library の
modint
である。詳しくはこちら。
これを使うことで、各演算を1行で行うことができ実装も簡単になる。
ただし、一つ注意したいのが、 の
の計算だ。
mint(10).pow(Nl)
としてしまうと、 の計算でオーバーフローしてしまうためうまくいかない。
mint(10).pow(l).pow(N)
のように、ひとつずつ計算していくこと。
コード
#include <bits/stdc++.h> #include <atcoder/modint> using namespace std; using namespace atcoder; using ll = long long; using mint = modint998244353; // ======================================== // int main() { ll N; cin >> N; string N_str = to_string(N); ll l = N_str.length(); mint p = mint(10).pow(l).pow(N) - 1; mint q = mint(10).pow(l) - 1; mint q_inv = q.inv(); mint result = p * q_inv * N; cout << result.val() << endl; return 0; }
実装時間: 25分