Codechef Eugene and big number(矩阵快速幂)
题目转化为
$f(n) = m * f(n - 1) + a$
$f(n + 1) = m * f(n) + a$
两式相减得
$f(n + 1) = (m + 1) * f(n) - m * f(n - 1)$
求$f(n)$
其中$m$为$10^{k}$ ($k$为$a$的位数)
那么利用矩阵快速幂加速就可以了。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
typedef long long LL;
struct Matrix{ LL arr[5][5];} init, unit, Unit;
int T;
LL a, n, mod;
inline LL Pow(LL a, LL b, LL Mod){
LL ret(1); for (; b; b >>= 1, (a *= a) %= Mod) if (b & 1) (ret *= a) %= Mod; return ret;
}
Matrix Mul(Matrix a, Matrix b){
Matrix c;
rep(i, 1, 2) rep(j, 1, 2){
c.arr[i][j] = 0;
rep(k, 1, 2) (c.arr[i][j] += (a.arr[i][k] * b.arr[k][j] % mod)) %= mod;
}
return c;
}
Matrix MatrixPow(Matrix a, LL k){
Matrix ret(Unit); for (; k; k >>= 1, a = Mul(a, a)) if (k & 1) ret = Mul(ret, a); return ret;
}
inline LL calc(LL n){
LL ret(0); for (; n; n /= 10) ++ret;
return ret;
}
int main(){
scanf("%d", &T);
while (T--){
Unit.arr[1][1] = Unit.arr[2][2] = 1;
scanf("%lld%lld%lld", &a, &n, &mod);
if (a == 0LL){
puts("0");
continue;
}
LL exp = calc(a), m = Pow(10, exp, mod);
LL f1 = a % mod, f2 = ((f1 * m) % mod + a) % mod;
LL f3 = ((f2 * m) % mod + a) % mod;
if (n == 1LL){
printf("%lld\n", f1 % mod);
continue;
}
if (n == 2LL){
printf("%lld\n", f2 % mod);
continue;
}
if (n == 3LL){
printf("%lld\n", f3 % mod);
continue;
}
LL num = (2 * mod - m) % mod;
init.arr[1][1] = f3, init.arr[1][2] = init.arr[2][1] = f2, init.arr[2][2] = f1;
unit.arr[1][1] = m + 1, unit.arr[1][2] = num, unit.arr[2][1] = 1, unit.arr[2][2] = 0;
Matrix mul = MatrixPow(unit, n - 3);
Matrix ret = Mul(mul, init);
printf("%lld\n", ret.arr[1][1]);
}
return 0;
}

浙公网安备 33010602011771号