矩阵乘法,矩阵快速幂,快速幂
矩阵乘法
在信息学竞赛中考矩阵乘法不是为了考基本运算,而是利用矩阵乘法的特性,配合快速幂求解递推式的第 n 项,以及一些图论的构造转化。
点击查看代码
Mat Mul(Mat a,Mat b){
Mat c;
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
c.arr[i][j] = 0;
}
}
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
for(int k = 0;k<n;k++){
c.arr[i][j] = (c.arr[i][j] + a.arr[i][k]*b.arr[k][j]);
}
}
}
return c;
}
矩阵快速幂
点击查看代码
Mat qMul(Mat a,int cnt){
Mat ans;
//I矩阵
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
ans.arr[i][j] = (i==j);
}
}
while(cnt>0){
if(cnt&1){
ans = Mul(ans,a);
}
a = Mul(a,a);
cnt>>=1;
}
return ans;
}
快速幂
点击查看代码
int qpow(int a,int cnt,int mod){
int res=1;
while(cnt>0){
if(cnt&1){
res=res*a%mod;
}
a = a*a%mod;
cnt>>=1;
}
return res;
}
例题一
https://ac.nowcoder.com/acm/contest/26656/1016
Fib函数的前n项的平方和等于F(n)*F(n+1);
利用矩阵快速幂求出F(n)和F(n+1)即可
点击查看代码
#include<bits/stdc++.h>
#define int long long
int mod = 1e9+7;
using namespace std;
struct Mat{
int arr[20][20];
};
int n = 2;
Mat Mul(Mat a,Mat b){
Mat c;
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
c.arr[i][j] = 0;
}
}
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
for(int k = 0;k<n;k++){
c.arr[i][j] = (c.arr[i][j] + a.arr[i][k]*b.arr[k][j])%mod;
}
}
}
return c;
}
Mat qMul(Mat a,int cnt){
Mat ans;
//I矩阵
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
ans.arr[i][j] = (i==j);
}
}
while(cnt>0){
if(cnt&1){
ans = Mul(ans,a);
}
a = Mul(a,a);
cnt>>=1;
}
return ans;
}
signed main(){
int num;
cin>>num;
Mat node;
int c[2][2] = {1,1,
1,0};
for(int i = 0;i<2;i++){
for(int j = 0;j<2;j++){
node.arr[i][j] = c[i][j];
}
}
Mat nodel;
int d[2][2] = {1,0,
1,0};
for(int i = 0;i<2;i++){
for(int j = 0;j<2;j++){
nodel.arr[i][j] = d[i][j];
}
}
Mat ans = Mul(qMul(node,num-1),nodel);//前项为矩阵的n-1次方,最后乘以{fib2,fib1};
int res = (ans.arr[0][0]*ans.arr[1][0])%mod;
cout<<res;
}
例题二
https://ac.nowcoder.com/acm/problem/18264
由题意可得:f[n−1] * f[n+1]−f[n] * f[n] = f[n-1] * f[n]-f[n-1]*f[n-1]
n的数据范围过大,远超出1e18,此提示规律题
不难发现n为奇数时,答案为1,为偶数时,答案为-1
点击查看代码
#include<bits/stdc++.h>
using namespace std;
string s;
int main(){
cin>>s;
int num = s.length();
if((s[num-1]-'0')%2==1) cout<<-1<<endl;
else cout<<1<<endl;
}
浙公网安备 33010602011771号