Atcoder357D题解(求解等比数列求和公式的推导)

解题思路

  1. 设连接之后的N等于N last,w = 10 ^ (N在10进制下的长度,例如N = 5,那么w = 10)
  2. N last = N + N * w + N * (w ^ 2) + N * (w ^ 3) + ..... + N * (w ^ n)
  3. 举个例子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
  4. 其实就是N last每次拼接的数学表示
  5. 那么化简一下上面的式子
  6. 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;
}

 

posted @ 2024-06-10 21:31  lwj1239  阅读(31)  评论(0)    收藏  举报