文章目录
先序
- 1、 先说一般数的快速幂,就是把幂指数拆成了二进制进行运算这样就把时间将到了logN(N为幂次数)
- 2、矩阵快速幂就是将快速幂中的数变成了矩阵,但是要注意这里矩阵必须是n✖n的
因为下面要介绍矩阵快速幂在logN的时间内求斐波那契数列
所以我们暂定矩阵为2 ✖ 2的
矩阵乘法的实现
//矩阵乘法的实现
void marix_mul(ll a[][2],ll b[][2])
{
int c[2][2];
memset(c,0,sizeof c);
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
for(int k = 0; k < 2; k++){
c[i][j] = (c[i][j] % mod + a[i][k] % mod* b[k][j] % mod) % mod;
}
}
}
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
a[i][j] = c[i][j];
}
}
}
矩阵快速幂
//矩阵快速幂
void marix_pow(ll n)
{
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
if(i == j) res[i][j] = 1;
else res[i][j] = 0;
}
}
while(n){
if(n % 2){
marix_mul(res,a);
}
marix_mul(a,a);
n >>= 1;
}
}
矩阵快速幂求斐波那契的公式
具体怎么推的,我也不知道。。权当公式记吧
那么有了这个公式,我们就可以利用矩阵快速幂求斐波那契了
我们只要把(1 1 1 0 )太弱了,矩阵不会打,这个矩阵利用快速幂求到第n次方,然后输出marix[0][1]即可
例题:Immortal Porpoises
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#define __int128 LL
using namespace std;
typedef long long ll;
const int mod = 1e9;
ll a[2][2],res[2][2];
//矩阵乘法
void marix_mul(ll a[][2],ll b[][2])
{
int c[2][2];
memset(c,0,sizeof c);
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
for(int k = 0; k < 2; k++){
c[i][j] = (c[i][j] % mod + a[i][k] % mod* b[k][j] % mod) % mod;
}
}
}
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
a[i][j] = c[i][j];
}
}
}
//矩阵快速幂
void marix_pow(ll n)
{
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
if(i == j) res[i][j] = 1;
else res[i][j] = 0;
}
}
while(n){
if(n % 2){
marix_mul(res,a);
}
marix_mul(a,a);
n >>= 1;
}
}
void marix_fib(ll n)
{
marix_pow(n);
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int k;
ll y;
scanf("%d%lld",&k,&y);
a[0][0] = a[0][1] = a[1][0] = 1;
a[1][1] = 0;
marix_pow(y);
printf("%d %lld\n",k,res[0][1]);
}
return 0;
}