矩阵快速幂的原理是跟普通的快速幂一样,不过原来是数与数相乘,而矩阵快速幂是矩阵与矩阵相乘;
矩阵快速幂是运用于处理一些表达式进行多次递归会超时的问题;难点就是怎样构造矩阵,比如f[ n ] = f[n - 1] + f[ n - 2],
那么构造成的矩阵为:
1 1
1 0;
模板:
typedef struct
{
ll a[7][7];
void Init()
{
memset(a,0,sizeof(0));
for(int i = 1; i < 7; i ++)
{
a[i][i] = 1;
}
}
}Matrix;
Matrix p =
{
1,2,1,4,6,4,1,
1,0,0,0,0,0,0,
0,0,1,4,6,4,1,
0,0,0,1,3,3,1,
0,0,0,0,1,2,1,
0,0,0,0,0,1,1,
0,0,0,0,0,0,1
};
Matrix Matrix_Mul(Matrix a,Matrix b)
{
Matrix c;
for(int i = 0; i < 7; i ++)
{
for(int j = 0; j < 7; j ++)
{
c.a[i][j] = 0;
for(int k = 0; k < 7; k ++)
{
c.a[i][j] += (a.a[i][k] * b.a[k][j]) % MOD;
c.a[i][j] %= MOD;
}
}
}
return c;
}
Matrix pow_Matrix(ll m)
{
Matrix ans,b = p;
memset(ans.a,0,sizeof(ans.a));
for(int i = 0; i < 7; i ++)
{
ans.a[i][i] = 1;
}
while(m)
{
if(m & 1)
{
ans = Matrix_Mul(ans,b);
}
m >>= 1;
b = Matrix_Mul(b,b);
}
return ans;
}
这是裸的矩阵快速幂,给出的图就是要进行相乘的矩阵,
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef long long ll;
const int maxn = 100 + 10;
#define mod 1000
struct Matrix
{
ll a[maxn][maxn];
}origin,res;
void Init(ll n)
{
memset(res.a,0,sizeof(res.a));
for(ll i = 0; i < n ; i ++)
{
res.a[i][i] = 1;
}
}
Matrix Matrix_multi(Matrix aa,Matrix bb,ll n)//两矩阵相乘的算法
{
Matrix ress;
memset(ress.a,0,sizeof(ress));
for(ll i = 0; i < n ; i ++)
{
for(ll j = 0; j < n ; j ++)
{
for(ll k = 0; k < n ; k ++)
{
ress.a[i][j] += aa.a[i][k] * bb.a[k][j];
}
}
}
return ress;
}
void Matrix_calc(ll n,ll k)//矩阵快速幂
{
Matrix origins = origin;
while(k)
{
if(k & 1)
{
res = Matrix_multi(res,origins,n);
}
origins = Matrix_multi(origins,origins,n);
k >>= 1;
}
}
int main()
{
int n,m;
while( ~ scanf("%d%d",&n,&m) && (n || m) )
{
Init(n);
memset(origin.a,0,sizeof(origin.a));
for(ll i = 1; i <= m ; i ++)
{
int x,y;
scanf("%d%d",&x,&y);
origin.a[x][y] = 1;
}
int q;
scanf("%d",&q);
for(ll i = 1; i <= q; i ++)
{
Init(n);
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
Matrix_calc(n,k);
cout << res.a[x][y] % mod <<endl;
}
}
return 0;
}
hdu5950 Recursive sequence
题意:f[ n ] = f[n - 1] + 2 * f[n - 2] + n * 4; n的范围< 2^31;
思路:数据范围很大,
首先一看这个题目,很容易想到构造矩阵:那么我们现在来分析一下怎么构造这个矩阵,那么 (n+1)^4 = n^4+4n^3+6n^2+4^n+1 所以光 (n+1)^4 这个矩阵就能构造出 5∗5 的一个矩阵来, 然后 f(n) = f(n−1)+2∗f(n−2) 这个是 2∗2 的矩阵,所以构造出来就应该是 7∗7 的转移矩阵 A :
{f(n),f(n−1),n^4,n^3,n^2,n,1}∗A={f(n+1),f(n),(n+1)^4,(n+1)^3,(n+1)^2,(n+1),1}
然后 f(n+1) = f(n)+2∗f(n−1)+(n+1)4, 可得矩阵 A:
Matrix p =
{
1,2,1,4,6,4,1,
1,0,0,0,0,0,0,
0,0,1,4,6,4,1,
0,0,0,1,3,3,1,
0,0,0,0,1,2,1,
0,0,0,0,0,1,1,
0,0,0,0,0,0,1
};
然后就是直接代码了:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MOD 2147493647
const int maxn = 200+ 20;
typedef struct
{
ll a[7][7];
void Init()
{
memset(a,0,sizeof(0));
for(int i = 1; i < 7; i ++)
{
a[i][i] = 1;
}
}
}Matrix;
Matrix p =
{
1,2,1,4,6,4,1,
1,0,0,0,0,0,0,
0,0,1,4,6,4,1,
0,0,0,1,3,3,1,
0,0,0,0,1,2,1,
0,0,0,0,0,1,1,
0,0,0,0,0,0,1
};
Matrix Matrix_Mul(Matrix a,Matrix b)
{
Matrix c;
for(int i = 0; i < 7; i ++)
{
for(int j = 0; j < 7; j ++)
{
c.a[i][j] = 0;
for(int k = 0; k < 7; k ++)
{
c.a[i][j] += (a.a[i][k] * b.a[k][j]) % MOD;
c.a[i][j] %= MOD;
}
}
}
return c;
}
Matrix pow_Matrix(ll m)
{
Matrix ans,b = p;
memset(ans.a,0,sizeof(ans.a));
for(int i = 0; i < 7; i ++)
{
ans.a[i][i] = 1;
}
while(m)
{
if(m & 1)
{
ans = Matrix_Mul(ans,b);
}
m >>= 1;
b = Matrix_Mul(b,b);
}
return ans;
}
int main()
{
int Tcase;
scanf("%d",&Tcase);
for(int ii = 1; ii <= Tcase; ii ++)
{
ll n,a,b;
scanf("%I64d%I64d%I64d",&n,&a,&b);
if(n == 1)
{
cout << a << endl;
continue;
}
if(n == 2)
{
cout << b << endl;
continue;
}
Matrix ans = pow_Matrix(n - 2);
ll anss = 0;
anss = (anss + ans.a[0][0] * b % MOD) % MOD;
anss = (anss + ans.a[0][1] * a % MOD) % MOD;
anss = (anss + ans.a[0][2] * 16 % MOD) % MOD;
anss = (anss + ans.a[0][3] * 8 % MOD) % MOD;
anss = (anss + ans.a[0][4] * 4 % MOD) % MOD;
anss = (anss + ans.a[0][5] * 2 % MOD) % MOD;
anss = (anss + ans.a[0][6] * 1 % MOD) % MOD;
cout << anss << endl;
}
return 0;
}