我试图优化我的代码来计算矩阵的n次幂。
在我拨打1
n
次之前,这太慢了。问题是,它构建得很好,但是当我运行它时,我的退出值void multiplySquare(long long A[2][2], long long B[2][2]){
long long result[2][2];
for (int i = 0; i < 2; i++){
for (int j = 0; j < 2; j++){
result[i][j] = 0;
for (int k = 0; k < 2; k++){
result[i][j] += A[i][k] * B[k][j];
}
}
}
for (int i=0; i<2; i++){
for (int j=0; j<2; j++){
A[i][j] = result[i][j];
}
}
}
void power(long long A[2][2], long long B[2][2], long long n){
if(n/2 != 0){
power(A, B, n/2);
}
if(n%2 != 0){
multiplySquare(A, B);
}
}
失败了。我相信我的算法是正确的,所以导致这种情况的原因是什么?
[编辑]添加了递归终止条件,但仍然存在相同的错误。
[再次编辑]我再次重新编写了递归部分,现在它似乎可以工作,但仅适用于{{1}}的某些输入。我不得不更多地玩弄它。任何帮助,将不胜感激。
{{1}}
答案 0 :(得分:4)
有效计算数字N
x
次幂的算法是:
如果N
为零,请返回1
如果N
为1,请返回x
计算(N/2)
- 权力。 y = x^(N/2)
如果N
为偶数,请返回y*y
如果N
为奇数,请返回x*y*y
如果您将该逻辑转换为您的案例,您将需要以下内容:
// Assuming that the result is returned in B.
void power(long long A[2][2], long long B[2][2], long long n)
{
if ( n == 0 )
{
makeIdentity(B);
return;
}
if ( n == 1 )
{
assign(A, B); // Make B same as A.
return;
}
power(A, B, n/2);
multiplySquare(B, B);
if(n % 2 != 0)
{
multiplySquare(B, A);
}
}
答案 1 :(得分:4)
我试图优化我的代码来计算矩阵的n次幂。
由于您的目标是优化,因此考虑对角矩阵具有微不足道的n次幂,即主对角线元素的第n次幂可能是一件好事。
所以,首先你应该对你的矩阵进行对角化。一种方法是找到初始矩阵A的特征向量和特征值,并利用以下关系:
A = P D P -1
其中P是包含A,P -1 的(列)特征向量的矩阵 是它的逆,D是包含特征值的对角矩阵。
然后: n = P D n P -1
上述等式:
答案 2 :(得分:1)
看来你的片段不是你的目标。我猜想你的意思是这样的:
void power(long long A[2][2], long long B[2][2], long long n){
if (n == 1) {
multiplySquare(A, B);
}
else if(n % 2 == 0) {
power(A, B, n / 2);
multiplySquare(A, A);
}
else {
power(A, B, (n - 1) / 2);
multiplySquare(A, A);
multiplySquare(A, B);
}