解题思路
- 设连接之后的N等于N last,w = 10 ^ (N在10进制下的长度,例如N = 5,那么w = 10)
- N last = N + N * w + N * (w ^ 2) + N * (w ^ 3) + ..... + N * (w ^ n)
- 举个例子N= 5,因为510进制的长度是1,所以w = 10,那么N last = 5 + 5 * 10(w) ^ 1 + 5 * 10(w) ^ 2 + 5 * 10(w) ^ 3 + 5 * 10(w) ^ 4 + 5 * 10(w) ^ 5
- 其实就是N last每次拼接的数学表示
- 那么化简一下上面的式子
- N last = N + N * w + N * (w ^ 2) + N * (w ^ 3) + ..... + N * (w ^ n)
= N * (w ^ 0 + w ^ 1 + w ^ 2 + w ^3 + .... + w ^ (n - 1))
如果不会乘法逆元的话就可以使用分治法求解等比数列的求和公式
设以公比为q, 一直到n的求和为sum(q, n) = q ^0 + q ^ 1 + q ^ 2 + ..... + q^n
那么当n是奇数时,我们可以化简为
sum(q, n) = q ^ 0 + q ^ 1 + q ^ ((n - 1) / 2) + q ^ ((n + 1) / 2) + q ^ (n + 3) / 2 + ........ + q ^ n
提出一个对于后半部分提出一个q ^ ((n + 1) / 2)原式等于
= q ^ 0 + q ^ 1 + q ^ ((n - 1) / 2) + q ^ ((n + 1) / 2) * (q ^ 0 + q ^ 1 + q ^ ((n - 1) / 2))
= (1 + q ^ ((n + 1) / 2)) * (q ^ 0 + q ^ 1 + q ^ ((n - 1) / 2))
那么不就是(1 + q ^ ((n + 1) / 2)) * sum(q, (n - 1) / 2)吗,时间复杂度O(logN)
代码实现
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#define sc scanf
#define pr printf
#define endl '\n'
#define sz(x) int((x).size())
#define all(x) x.begin(), x.end()
#define pb(x) push_back(x)
using namespace std;
using ll = long long;
typedef pair<ll, ll> pll;
const int INF = 0x3f3f3f3f;
const int N = 2 * 1e5 + 10;
const int mod = 998244353;
int d[4][2] = {
{-1, 0}, {1, 0}, {0, -1}, {0, 1}
};
int t;
ll n;
ll qpow(ll a, ll b, ll p) {
ll ans = 1;
while (b) {
if (b & 1) {
ans = ans * a % p;
}
a = a * a % p;
b >>= 1;
}
return ans % p;
}
ll sum(ll p, ll k) {
if (k == 0) {
return 1;
}
if (k % 2 == 0) {
return (qpow(p, k, mod) + sum(p, k - 1) + mod) % mod;
}
return (1 + qpow(p, (k + 1) / 2, mod)) % mod * sum(p, (k - 1) / 2) % mod;
}
void solve() {
cin >> n;
ll tmp = n;
int cnt = 0;
while (tmp) {
tmp /= 10;
cnt ++;
}
ll w = qpow(10, cnt, mod);//求出公比
ll ans = n % mod * sum(w, n - 1) % mod;
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
t = 1;
while (t--) {
solve();
}
return 0;
}
标签:10,等比数列,int,题解,ll,Atcoder357D,define,sum,mod From: https://www.cnblogs.com/lwj1239/p/18241066