快速幂
原理:
x
y
x^y
xy中的
y
y
y 转化成二进制数,然后每一个
1
1
1 对应
x
x
x 的
i
i
i 次方
这样把
x
y
x^y
xy转化成了
x
y
x^y
xy =
x
a
x^a
xa *
x
b
x^b
xb *
x
c
x^c
xc…
通过对
x
x
x 不断翻倍的过程,来匹配y转成二进制的
1
1
1。
如果为
1
1
1 ,则记录的答案就会乘
x
x
x 的 相应次方。
p p p 为模数
例题:
luogu P1226 快速幂[模版]
luogu P2817 宋荣子的城堡
luogu P3197 越狱
int pow(int x, int y)
{
int ans = 1;
while(y)
{
if(y&1) ans = ans*x%p;
x = x*x%p;
y >>= 1;
}
return ans;
}
矩阵快速幂
矩阵相乘的条件:
矩阵
A
A
A 有
n
n
n 行
m
m
m 列, 矩阵
B
B
B 有
m
m
m 行
p
p
p 列 。
矩阵
C
=
A
∗
B
C = A * B
C=A∗B ,矩阵
C
C
C 为
n
n
n 行
p
p
p 列。
n
、
m
、
p
n、m、p
n、m、p 要满足上述限制。
把矩阵当成一个元素,重复上边的普通的快速幂就好了。
注意:用结构体代表矩阵,二维数组来存储数字,重载结构体的
∗
*
∗ 运算。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <ctime>
#include <queue>
#include <set>
using namespace std;
long long n, k, p = 1e9+7;
struct Matrix
{
long long s[110][110];
}a,ans;
Matrix operator * (const Matrix &x, const Matrix &y)
{
Matrix t;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
t.s[i][j] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
for(int k = 1; k <= n; k++)
t.s[i][j] = (t.s[i][j] + x.s[i][k] * y.s[k][j]) % p;
return t;
}
long long read()
{
long long rt = 0, in = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') in = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {rt = rt * 10 + ch - '0'; ch = getchar();}
return rt * in;
}
int main()
{
n = read(), k = read();
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
a.s[i][j] = read();
ans.s[i][i] = 1;
}
while(k)
{
if(k & 1) ans = ans * a;
a = a * a;
k >>= 1;
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
printf("%lld ",ans.s[i][j]);
printf("\n");
}
system("pause");
return 0;
}
例题:[模版]矩阵快速幂