矩阵快速幂的递推方面的应用(重要的应用之一); 矩阵快速幂中最重要的是矩阵的构造。构造的矩阵都是方阵, 只有方阵才能快速相乘。
NYOJ 301 递推求值
题目连接:http://acm.nyist.net/JudgeOnline/problem.php?pid=301
由题意的递推式可知,我们构建这样的矩阵相乘的递推式
| b, 1, 0 |
|F(N-1), F(N-2), c| * | a, 0, 0 | = |F(N), F(N-1), c| ;
| 1, 0, 1 |
可以得到
| b, 1, 0 | ^ n-2
|F(N), F(N-1), c|= |F(2), F(1), c| * | a, 0, 0 | ;
| 1, 0, 1 |
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N = 3;
const int mod = 1000007;
int f1, f2, a, b, c, n;
struct Node
{
int row, cal;
int s[N][N];
Node()
{
row = cal = 3;
s[0][0] = b, s[0][1] = 1, s[0][2] = 0;
s[1][0] = a, s[1][1] = 0, s[1][2] = 0;
s[2][0] = 1, s[2][1] = 0, s[2][2] = 1;
}
};
Node mem(Node x, int c)
{
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++)
x.s[i][j] = c;
return x;
}
Node Matble(Node x, Node y)
{
Node ans;
ans.row = x.row;
ans.cal = y.cal;
ans = mem(ans, 0);
for(int i = 0; i < ans.row; i++)
for(int j = 0; j < ans.cal; j++){
for(int k = 0; k < x.cal; k++)
ans.s[i][j] = (int)(ans.s[i][j] + (long long)x.s[i][k] * y.s[k][j] % mod + mod) % mod;
return ans;
}
int pow_Matble(int n)
{
if(n == 1)
return f1;
else if(n == 2)
return f2;
n -= 2;
Node ans, temp;
ans.row = 1;
ans.cal = 3;
ans.s[0][0] = f2, ans.s[0][1] = f1, ans.s[0][2] = c;
while(n > 0)
{
if(n%2 == 1)
ans = Matble(ans, temp);
temp = Matble(temp, temp);
n /= 2;
}
return ans.s[0][0];
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d%d%d%d", &f1, &f2, &a, &b, &c, &n);
printf("%d\n", pow_Matble(n));
}
return 0;
}
NYOJ1000 又见斐波那契数列
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=1000
本题就是斐波那契数列的加强版, 首先我们化简递推式, 我们发现F(n) = F(1)^m1 * F(0)^M0;而m1, m0, 就是斐波那契数列, 所以我们用矩阵快速幂求出m1, m0; 最用快速幂求出F(1)^m1 和F(0)^m0, 然后再相乘。
这道题让求的是F(n)对1000000007; 所以我们在用费马小定理就解决了, 费马小定理是指 ( a^p-1 )%p = 1(a, p互素);我们可以简单理解为
(a^m)%p = ( a^ (m % (p-1) ) )%p ; 这样就解决这道题了。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 2;
const int mod = 1000000007;
struct Node
{
int row, cal;
int s[maxn][maxn];
Node()
{
row = cal = 2;
s[0][0] = 1, s[0][1] = 1;
s[1][0] = 1, s[1][1] = 0;
}
};
Node Matble(Node x, Node y)
{
Node ans;
ans.row = x.row;
ans.cal = y.cal;
for(int i = 0; i < ans.row; i++)
for(int j = 0; j < ans.cal; j++)
ans.s[i][j] = 0;
for(int i = 0; i < ans.row; i++)
for(int j = 0; j < ans.cal; j++)
for(int k = 0; k < x.cal; k++)
ans.s[i][j] = (int)(ans.s[i][j] + (long long)x.s[i][k] * y.s[k][j] % (mod-1)) % (mod-1);
return ans;
}
void pow_Matble(int n, int& m0, int& m1)//快速幂(矩阵的)
{
if(n == 0)
{
m0 = 1;
m1 = 0;
return ;
}
Node ans, temp;
ans.row = 1, ans.cal = 2;
ans.s[0][0] = 1, ans.s[0][1] = 0;
n -= 1;
while(n > 0)
{
if(n&1)
ans = Matble(ans, temp);//调用矩阵乘法
temp = Matble(temp, temp);//调用矩阵乘法
n /= 2;
}
m1 = ans.s[0][0]; m0 = ans.s[0][1];
}
int pow_mod(int k, int m)//快速幂 (整数的)
{
int ans = 1, temp = k;
while(m > 0)
{
if(m&1)
ans = (int)((long long)ans * temp % mod);
temp = (int)((long long)temp * temp % mod);
m /= 2;
}
return ans;
}
void solve(int a, int b, int n)
{
int m0, m1;
pow_Matble(n, m0, m1);
int ans1 = pow_mod(a, m0);
int ans2 = pow_mod(b, m1);
int ans = (long long)ans1 * ans2 % mod;
printf("%d\n", ans);
}
int main()
{
int a, b, n;
while(~scanf("%d%d%d", &a, &b, &n))
{
solve(a, b, n);
}
return 0;
}