十进制快速幂&&十进制矩阵快速幂

it2026-01-28  12

想必大家都会二进制快速幂, 普通的快速幂中, 将指数拆为二进制数,基数为 2 的次方。

十进制快速幂仅仅是将基数变为了10的次方,只要对普通快速幂的思想了解, 这个就很简单了

 例如求 =  

ll t_pow(ll a, ll b) { ll res = 1; while (b > 0) { ll now = a; for (int i = 1; i <= b % 10; i++) // 当前位数字为几, 即乘几次 res = (res * a) % mod; for (int i = 2; i <= 10; i++) // a = a ^ 10 a = a * now % mod; b /= 10; } return res; }

显然每次我们都要有个乘9次的操作, 可以用快速幂的思想倍增求, 这样就可以优化到3次

ll t_pow(ll a, ll b) { ll res = 1; while (b > 0) { for (int i = 1; i <= b % 10; i++) res = (res * a) % mod; ll x = a * a % mod; // a ^ 2 ll y = x * x % mod; // a ^ 4 ll z = y * y % mod; // a ^ 8 a = z * x % mod; // a ^ 10 b /= 10; } return res % mod; }

至于矩阵快速幂的话, 跟普通的矩阵快速幂差别也就仅仅在这里

例如牛客多校第五场 B: generator 1

https://ac.nowcoder.com/acm/contest/885/B

这题给出  满足 

求第n项 

显然直接用二进制快速幂求会超时。

对做一次矩阵乘法, 得到的即是与

所以乘n次后, 取m[1][0]即是答案

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e6 + 10; ll A, B, x0, x1; ll m; char s[N]; struct M{ ll m[2][2]; M() { memset(m, 0, sizeof m); } }; M mul(M a, M b) { M ans; for (ll i = 0; i < 2; i++) for (ll j = 0; j < 2; j++) { for (ll k = 0; k < 2; k++) ans.m[i][j] = (ans.m[i][j] + a.m[i][k] * b.m[k][j] % m) % m; } return ans; } void fpow(ll n) { M a, b; a.m[0][0] = A; a.m[0][1] = B; a.m[1][0] = 1; b.m[0][0] = b.m[1][1] = 1; while (n >= 0) { ll cnt = s[n] - '0'; M now = a; for (int i = 1; i <= cnt; i++) b = mul(b, a); M c[2]; a = mul(a, a); // 2 c[0] = mul(a, a); // 4 c[1] = mul(c[0], c[0]); // 8 a = mul(a, c[1]); n--; } M ans; ans.m[0][0] = x1; ans.m[1][0] = x0; ans = mul(b, ans); cout << ans.m[1][0] << endl; } int main(){ cin >> x0 >> x1 >> A >> B; scanf("%s", s); cin >> m; ll len = strlen(s); fpow(len - 1); return 0; }

 

最新回复(0)