题目链接:HDU 4549 M斐波那契数列
题目大意:
题解:
先找规律:
(F_0=a,)
(F_1=b,)
(F_2=a imes b,)
(F_3=a imes b^2,)
(F_4=a^2 imes b^3,)
(F_5=a^3 imes b^5,)
(...)
(F_n=a^{f_{n-1}} imes b^{f_n})((f_n)为斐波那契数列)
所以题目就变成了用矩阵快速幂求斐波那契数列。
构造矩阵:
[left(egin{matrix}
f_i \
f_{i-1}
end{matrix}
ight)
=
left(egin{matrix}
1 & 1 \
1 & 0
end{matrix}
ight)
imes
left(egin{matrix}
f_{i-1} \
f_{i-2}
end{matrix}
ight)
]
所以:
[left(egin{matrix}
f_n \
f_{n-1}
end{matrix}
ight)
=
left(egin{matrix}
1 & 1 \
1 & 0
end{matrix}
ight)^{n-1}
imes
left(egin{matrix}
1 \
0
end{matrix}
ight)
]
因为结果需要对(1e9+7)取余,由费马小定理可知(a^{p-1}equiv 1(mod p)),
由此可得:
[ans=(a^{f_{n-1}}\%mod imes b^{f_n}\%mod)\%mod
]
[=((a^{f_{n-1}\%(mod-1)} imes a^{(mod-1)^{[f_{n-1}div (mod-1)]}})\%mod+(b^{f_n\%(mod-1)} imes b^{(mod-1)^{[f_ndiv (mod-1)]}})\%mod)\%mod
]
[=(a^{f_{n-1}\%(mod-1)}\%mod+b^{f_n\%(mod-1)}\%mod)\%mod
]
所以在矩阵快速幂中对(1e9+6)取余,在快速幂中对(1e9+7)取余。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
const int mod = 1e9 + 7;
struct Matrix { // 矩阵
int row, col;
ll num[2][2];
};
Matrix multiply(Matrix a, Matrix b) { // 矩阵乘法
Matrix temp;
temp.row = a.row, temp.col = b.col;
memset(temp.num, 0, sizeof(temp.num));
for (int i = 0; i < a.row; ++i)
for (int j = 0; j < b.col; ++j)
for (int k = 0; k < a.col; ++k)
temp.num[i][j] = (temp.num[i][j] + a.num[i][k] * b.num[k][j]) % (mod - 1);
return temp;
}
Matrix MatrixFastPow(Matrix base, ll k) { // 矩阵快速幂
Matrix ans;
ans.row = ans.col = 2;
ans.num[0][0] = ans.num[1][1] = 1;
ans.num[0][1] = ans.num[1][0] = 0;
while (k) {
if (k & 1) ans = multiply(ans, base);
base = multiply(base, base);
k >>= 1;
}
return ans;
}
ll fastPow(ll n, ll k) { // 快速幂
ll ans = 1;
while (k) {
if (k & 1) ans = ans * n % mod;
n = n * n % mod;
k >>= 1;
}
return ans;
}
int main() {
ll a, b, n;
Matrix base;
base.row = base.col = 2;
base.num[0][0] = base.num[0][1] = base.num[1][0] = 1;
base.num[1][1] = 0;
while (~scanf("%lld%lld%lld", &a, &b, &n)) {
if (!n) {
printf("%lld
", a);
} else {
Matrix ans = MatrixFastPow(base, n - 1);
printf("%lld
", fastPow(a, ans.num[1][0]) * fastPow(b, ans.num[0][0]) % mod);
}
}
return 0;
}