链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
已知数列f(n) f(n)\spacef(n) 满足 f(0) =x,f(1)=y,f(n)=af(n−1)+bf(n−2)f(0)\space = x, f(1)=y, f(n)=af(n-1)+bf(n-2)f(0) =x,f(1)=y,f(n)=af(n−1)+bf(n−2)。
输入x,y,a,b,n, 求f(n)对109+710^9+7109+7取模的结果。
输入描述:
第一行输入一个整数T,表示T组测试用例。
接下来T行,每行5个数,x,y,a,b,n
1≤T≤1041 \le T \le 10^41≤T≤104
0≤x,y,a,b≤1090 \le x,y,a,b \le 10^90≤x,y,a,b≤109
0≤n≤10180 \le n \le 10^{18}0≤n≤1018
输出描述:
输出T行,每行一个答案。
输入:
7
0 1 1 1 0
0 1 1 1 1
0 1 1 1 2
0 1 1 1 3
0 1 1 1 4
0 1 1 1 5
3 4 5 6 3
输出:
0
1
1
2
3
5
214
答案:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e3 + 10;
const ll mod = 1e9 + 7;
ll x, y, a, b, n;
struct M{
ll a[3][3];
M(){
memset(a, 0, sizeof(a));
}
}dis, ans;
void init(){//创建单位矩阵以及如快速幂一样的不断叠加的矩阵
dis.a[1][1] = a; dis.a[1][2] = 1;
dis.a[2][1] = b; dis.a[2][2] = 0;
ans.a[1][1] = (a * y + b * x) % mod;
ans.a[1][2] = ans.a[2][1] = y; ans.a[2][2] = x;
}
M getM(M x, M y){//矩阵的计算方法
M temp;
for(int i = 1; i <= 2; i++){
for(int j = 1;j <= 2; j++){
for(int k = 1; k <= 2; k++){
temp.a[i][j] = (temp.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;
}
}
}
return temp;
}
void power(ll p){//幂级计算判断为奇数相当于转化为二进制右移
while(p){
if(p % 2 == 1){
ans = getM(ans, dis);
}
p /= 2;
dis = getM(dis, dis);
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t; cin >> t;
while(t--){
cin >> x >> y >> a >> b >> n;
init();
power(n);
cout << ans.a[2][2] << '\n';
}
return 0;
}
解释{ai}
矩阵快速幂是一种高效的算法,用于计算矩阵的高次方,其时间复杂度从朴素的O(n)降低到O(logn)。这种算法在解决一些递推关系、动态规划等问题时非常有用,特别是在需要频繁进行矩阵乘法操作时。以下是对矩阵快速幂的详细解释:
一、基本概念
矩阵快速幂是用来高效地计算矩阵的高次方的算法。在常规方法中,计算一个矩阵的n次方需要连续乘以该矩阵n-1次,但这种方法的时间复杂度较高。矩阵快速幂通过利用矩阵乘法的结合律,将计算过程优化为对数时间复杂度。
二、基本原理
矩阵快速幂的基本原理与整数快速幂类似,都是利用分治的思想。在整数快速幂中,我们将指数表示为二进制形式,然后利用指数的每一位来决定是否将当前的底数乘以自己(即平方操作),并相应地更新指数。在矩阵快速幂中,我们将这个过程应用到矩阵上,即将矩阵的幂次操作转化为矩阵的乘法操作。
具体来说,我们可以将矩阵的n次方表示为一系列矩阵乘法的结果。首先,我们将n表示为二进制形式,然后从最低位开始,依次判断每一位是否为1。如果某一位为1,则将当前的矩阵(初始时为原矩阵或单位矩阵)乘以该矩阵的相应次方(通过之前的计算得到)。然后,将当前的矩阵平方(即乘以自己),并将指数右移一位(即去掉最低位)。这个过程一直持续到指数为0为止。
三、算法步骤
- 初始化:将结果矩阵初始化为单位矩阵(如果n为0,则直接返回单位矩阵)。
- 二进制分解:将n表示为二进制形式。
- 循环计算:从最低位开始遍历n的二进制表示中的每一位。
- 如果当前位为1,则将结果矩阵乘以原矩阵的相应次方(通过之前的计算得到)。
- 将原矩阵平方(即乘以自己)。
- 将指数右移一位(即去掉最低位)。
- 返回结果:当指数为0时,循环结束,返回结果矩阵。
四、注意事项
- 矩阵大小:矩阵快速幂通常用于方阵(即行数和列数相等的矩阵)。如果矩阵不是方阵,可能需要通过添加零行或零列来将其转换为方阵。
- 取模运算:在计算过程中,如果涉及到大数运算,可能需要使用取模运算来防止整数溢出。这通常需要在矩阵乘法函数中进行处理。
- 精度问题:在浮点数运算中,矩阵快速幂可能会受到精度问题的影响。因此,在需要高精度结果时,应使用整数或高精度库来进行计算。
五、应用示例
矩阵快速幂在解决斐波那契数列等递推关系问题时非常有用。通过构造一个特定的矩阵,我们可以将递推关系转化为矩阵的幂次运算,然后利用矩阵快速幂来快速求解。此外,矩阵快速幂还可以用于求解线性方程组、图论中的路径计数等问题。
总之,矩阵快速幂是一种高效的算法,它通过利用矩阵乘法的结合律和分治的思想,将矩阵的高次方运算的时间复杂度降低到对数级别。这种算法在解决一些递推关系、动态规划等问题时具有广泛的应用价值。