abc 293 E 题解
abc 293 E
题意
给定 \(A, X, M\),请你求出 \(\sum \limits _{i = 0} ^ {X - 1} A ^ i \mod m\)。
\(1 \le X \le 10 ^ {12}, 1 \le A, M \le 10 ^ 9\)
思路
首先,这题有一个很明显的暴力:枚举所有的 \(i\),将所有 \(A ^ i\) 累加起来。
但是这样的话,时间复杂度为 \(O(X)\),妥妥的超时。
所以我们可以考虑一种递归分治的做法。
令 \(S(n) = A ^ 1 + A ^ 2 + \dots A ^ n\)。
- 若 \(n\) 为偶数:
\(S(n) = S(n / 2) + A ^ {n / 2 + 1} + \dots A ^ n\)
$ = S(n / 2) + (A ^ 1 \times A ^ {n / 2}) + \dots + (A ^ {n / 2} \times A ^ {n / 2})$
$ = S(n / 2) + (A ^ 1 + A ^ 2 + \dots A ^ {n / 2}) \times A ^ {n / 2}$
$ = S(n / 2) + S(n / 2) \times A ^ {n / 2}$
实际上,\(n\) 为奇数的情况与偶数并没有什么不同,只是要在求和的时候多加上一个 \(A ^ n\) 而已。
- 若 \(n\) 为奇数:
\(S(n) = S(\lfloor n / 2 \rfloor) + A ^ {\lfloor n / 2 \rfloor + 1} + \dots A ^ n\)
$ = S(\lfloor n / 2 \rfloor) + (A ^ 1 \times A ^ {\lfloor n / 2 \rfloor}) + \dots + (A ^ {\lfloor n / 2 \rfloor} \times A ^ {\lfloor n / 2 \rfloor}) + A ^ n$
$ = S(\lfloor n / 2 \rfloor) + (A ^ 1 + A ^ 2 + \dots A ^ {\lfloor n / 2 \rfloor}) \times A ^ {\lfloor n / 2 \rfloor} + A ^ n$
$ = S(\lfloor n / 2 \rfloor) + S(\lfloor n / 2 \rfloor) \times A ^ {\lfloor n / 2 \rfloor} + A ^ n$
由于这里我定义的是 \(S(n) = A ^ 1 + \dots + A ^ n\),所以要将 \(A ^ 0\) 再最后单独计算一下。
代码
#include <bits/stdc++.h>
using namespace std;
int a, m;
long long w;
struct Node {
long long x, y;
};
Node P(long long t) {
if (t <= 1) {
/*
这里有一个问题,之所以要写成 t <= 1,是因为 w 有可能为 1
若 w = 1,那么传进来的 t 就会是 0,如果只判断 t == 1,会无限递归,RE
*/
return {t * a % m, t * a % m};
}
Node x = P(t / 2);
long long p = x.x * x.x % m;
// x.x 为 A ^ (t / 2),x.y 为 A ^ 1 + ... + A ^ (t / 2)
x.y = (x.y + x.y * x.x % m) % m; // 求和
if (t % 2 == 1) { // 若 n 为奇数
p = p * a % m, x.y = (x.y + p) % m;
}
x.x = p;
return x;
}
int main() {
cin >> a >> w >> m;
// P(w - 1) 求 A ^ 1 + ... + A ^ (w - 1)
cout << (P(w - 1).y + 1) % m;
return 0;
}