参考:
https://zhuanlan.zhihu.com/p/95902286
https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode-solution/#comment
对于契科夫数列问题以及爬楼梯问题的解决办法。
#include <cstdio>
#define MOD 1000000007
typedef long long ll;
struct matrix
{
ll a1, a2, b1, b2;
matrix(ll a1, ll a2, ll b1, ll b2) : a1(a1), a2(a2), b1(b1), b2(b2) {}
matrix operator*(const matrix &y)
{
matrix ans((a1 * y.a1 + a2 * y.b1) % MOD,
(a1 * y.a2 + a2 * y.b2) % MOD,
(b1 * y.a1 + b2 * y.b1) % MOD,
(b1 * y.a2 + b2 * y.b2) % MOD);
return ans;
}
};
matrix qpow(matrix a, ll n)
{
matrix ans(1, 0, 0, 1); //单位矩阵
while (n)
{
if (n & 1)
ans = ans * a;
a = a * a;
n >>= 1;
}
return ans;
}
int main()
{
ll x;
matrix M(0, 1, 1, 1);
scanf("%lld", &x);
matrix ans = qpow(M, x - 1);
printf("%lld\n", (ans.a1 + ans.a2) % MOD);
return 0;
}
思路是:将幂按照二进制位来解决,每次仅限底数的平方运算。
如果最后一位是1则多乘一个底数a
否则a*=a,为下次乘积做准备。
每次n右移一位,直到所有位0
时间复杂度从O(n)降低到O(logn)
扫描二维码关注公众号,回复:
13164642 查看本文章
