luogu P3216 [HNOI2011]數學作業 矩陣快速冪
阿新 • • 發佈:2018-12-28
題意
- 把 的數寫在一行,求這個數對 取模的結果,
把這些東西寫在一行看成一個遞推的過程
用矩陣乘法優化這個遞推就好了,跟裸題沒什麼區別
#include <bits/stdc++.h>
#define For(i, a, b) for (int i = a; i <= b; ++ i)
using namespace std;
long long n, mod, pow10[19];
struct Martix {
int a[3][3];
Martix(int opt = 0) {
memset(a, 0, sizeof(a));
if (opt) a[0][0] = a[1][1] = a[2][2] = 1;
}
Martix operator * (const Martix &T) const {
Martix res;
For(i, 0, 2) For(j, 0, 2) For(k, 0, 2)
(res.a[i][j] += 1ll * a[i][k] * T.a[k][j] % mod) %= mod;
return res;
}
}now, zhuan;
Martix qpow(Martix a, long long x) {
Martix ret(1);
while (x) {
if (x & 1) ret = ret * a;
x >>= 1, a = a * a;
}
return ret;
}
int main() {
#ifdef ylsakioi
freopen("3216.in", "r", stdin);
freopen("3216.out", "w", stdout);
#endif
pow10[0] = 1, cin >> n >> mod;
For(i, 1, 18) pow10[i] = 10ll * pow10[i - 1];
zhuan.a[1][0] = zhuan.a[1][1] = zhuan.a[2][1] = zhuan.a[2][2] = zhuan.a[2][0] = 1;
now.a[0][2] = 1;
For(i, 1, 18) if (pow10[i] / 10 <= n) {
zhuan.a[0][0] = pow10[i] % mod;
now = now * qpow(zhuan, min(n, pow10[i]) - pow10[i - 1]);
}
printf("%d\n", (now * zhuan).a[0][0]);
return 0;
}