実行時間制限: 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分