矩阵快速幂
本题要点:
1、递推关系,推导矩阵:
起始矩阵 res
res[0][0] = ans, res[0][1] = 1
res[1][0] = 0, res[1][1] = 0
i 是奇数的时候, 乘上矩阵 x
x[0][0] = 2, x[0][1] = 0
x[1][0] = 1, x[1][1] = 1
那么 res * x 的结果矩阵 y
y[0][0] = 2 * ans + 1, y[0][1] = 1
y1][0] = 0, y[1][1] = 0
同理 i是偶数,乘上矩阵 z
z[0][0] = 2, z[0][1] = 0
z[1][0] = 0, z[1][1] = 1
因此 进行n次矩阵相乘运算,就是间隔地乘以矩阵 x, z, 形式如下:
res * x * z * x * z * x * z ....
2、当n是偶数的时候,就是乘以 n / 2 次的矩阵 x * z.
当n是奇数的时候,乘以n / 2 次的矩阵 x * z, 再乘以矩阵 z 一次。
矩阵快速幂, 套模板即可。但是 Matrix 的 m一定要用 long long, 否则会爆 int
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MaxN = 2;
int n;
long long mod;
struct Matrix
{
long long m[MaxN][MaxN];
Matrix()
{
memset(m, 0, sizeof m);
}
};
Matrix multi(Matrix a, Matrix b)
{
Matrix res;
for(int i = 0; i < MaxN; ++i)
for(int j = 0; j < MaxN; ++j)
{
for(int k = 0; k < MaxN; ++k)
{
res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % mod;
}//m一定要用 long long, 否则会爆 int
}
return res;
}
Matrix fastm(Matrix res, Matrix a, int n)
{
while(n)
{
if(n & 1)
{
res = multi(res, a);
}
a = multi(a, a);
n >>= 1;
}
return res;
}
int main()
{
while(scanf("%d%lld", &n, &mod) != EOF)
{
Matrix res, a, b;
res.m[0][1] = 1;
a.m[0][0] = 4, a.m[1][0] = 2, a.m[1][1] = 1;
b.m[0][0] = 2, b.m[1][0] = 1, b.m[1][1] = 1;
res = fastm(res, a, n / 2);
if(n & 1)
res = fastm(res, b, 1);
printf("%lld\n", res.m[0][0]);
}
return 0;
}
/*
1 10
3 100
*/
/*
1
5
*/