設 爲知足如下條件的字符串個數:html
試求 模 獲得的值。c++
試求 。web
首先考慮長度爲 的答案是什麼。app
首先全部循環節小於 的串是不合法的,這十分顯然。svg
而後對於一個不具備循環節的串,咱們能夠轉它( ),能夠轉出 個互不相同的串。下面咱們證實這 個串中有且僅有一個是合法的。spa
考慮設 爲 個串中字典序最小的串,若它不合法,則存在一個後綴 。因爲 是字典序最小的,所以 的長度不超過 。3d
因爲
是字典序最小的,所以若是設
去掉
爲
,則
是
的前綴。
而後考慮轉到
的字符串。
因爲
是字典序最小的,所以對應字符存在以下關係:code
此時紅色後綴循環移位後獲得orm
假設有兩個串合法,設爲 ,考慮 設 在 中的位置的後綴是 ,另外一個是 ,知 (補 0),而 (定義),故 ,與 矛盾!xml
所以咱們只須要算循環節等於 的串的個數,設爲 。
事實上這很是好算啊!易知 ,因此 (莫比烏斯反演)!
注意到這是杜教篩簡單題,所以 求解。(能夠 ,只須要把 map 和算 sum(i10i) 換掉,前者能夠只記憶化 i 而不是 N/i,後者能夠分塊預處理來 O(1) 算 10^n)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int NN = 5000000; const int MOD = 258280327; int mu[NN + 5], P[NN + 5], pl; ll sum[NN + 5], ans, N; bool np[NN + 5]; map<ll, ll> M; ll power(ll a, ll b, ll p = MOD) { ll ret = 1; a %= p; for (; b; a = a * a % p, b >>= 1) if (b & 1) ret = ret * a % p; return ret; } const ll inv2 = power(2, MOD - 2), inv9 = power(9, MOD - 2); ll getS(ll n) { if (n <= NN) return sum[n]; if (M.find(n) != M.end()) return M[n]; ll s = 1; for (ll i = 2, j; i <= n; i = j + 1) { j = n / (n / i); s = (s - getS(n / i) * (i + j) % MOD * (j - i + 1) % MOD * inv2) % MOD; } M[n] = s; return s; } inline ll S(ll n) { ll pw = power(10, n + 1); n %= MOD; return (pw * n - (pw - 10) * inv9) % MOD * inv9 % MOD; } int main() { scanf("%lld", &N), mu[1] = 1; for (int i = 2; i <= NN; ++i) { if (!np[i]) P[++pl] = i, mu[i] = -1; for (int j = 1; j <= pl && i * P[j] <= NN; ++j) { np[i * P[j]] = 1; if (i % P[j]) mu[i * P[j]] = mu[i] * mu[P[j]]; else { mu[i * P[j]] = 0; break; } } } for (int i = 1; i <= NN; ++i) sum[i] = (sum[i - 1] + i * mu[i]) % MOD; getS(N); for (ll i = 1, j; i <= N; i = j + 1) { j = N / (N / i); ans = (ans + getS(N / i) * (S(j) - S(i - 1))) % MOD; } printf("%lld\n", (ans + MOD) % MOD); return 0; }