bug调试---1、斐波那契数列的矩阵快速幂解法bug
一、总结
一句话总结:
发现问题出在矩阵的快速幂里面,因为函数传n过去的时候指定的是int,而本题的n<2^63,所以n本来应该是long long类型的
错误原因:这里的n传参写成了int //矩阵的快速幂 //这里的n写成int类型有问题,这里要是long long Matrix pow(Matrix a, long long n) { Matrix ans, base = a; ans.row = 2; ans.column = 2; ans.v[1][1] = ans.v[2][2] = 1; while (n) { if (n % 2 == 1) ans = multiply(ans, base); base = multiply(base, base); n = n / 2; } return ans; }
1、解决斐波那契数列矩阵快速幂代码的bug的启示?
a、出现问题,要分析问题出现的原因,这样问题就比较好比较快的解决
b、或者可以参照别人的解决方式(代码),这样站在别人的肩膀上,也很快
2、解决bug如果没法看日志,其它一个比较快的方法是什么,比如(斐波那契数列矩阵快速幂代码的bug)?
二分法测bug,我们拿有问题的程序和标准程序的答案来做对比,逐步大批量的增大n,看看问题出现在哪个节点
二、斐波那契数列的矩阵快速幂解法bug
博客对应课程的视频位置:
1、问题
求斐波那契数列第n项 mod 10^9+7的值
【数据范围】
对于100%的数据,1<=n<2^63。
题目位置:P1962 斐波那契数列 - 洛谷 | 计算机科学教育新生态
https://www.luogu.com.cn/problem/P1962
这个数据量O(n)的算法肯定过不了,要O(logn)
所以可以用矩阵快速幂解法
结果代码写出来,
百分之80的数据是对的,只有20%不对,这不对的百分之20,全部是数据量比较大的情况
2、解决过程
出现问题,要分析问题出现的原因,这样问题就比较好比较快的解决
或者可以参照别人的解决方式,这样站在别人的肩膀上,也很快
这个问题后面的项和前面的项是相关的,所以如果前面的项出错了,那么后面的一般会出错
我们拿有问题的程序和标准程序的答案来做对比
逐步大批量的增大n,看看问题出现在哪个节点
可以二分法测bug
我们有可以来打印前1-200的结果,比较是否有问题
测试发现
n为int最大值之前都是没有问题的
10 0000 0000:10亿,21亿都是没有问题
当n超过int之后,两个程序的结果就不一样了,
证明肯定是因为n(1<=n<2^63)太大了,
导致超过int出现问题,
确定问题出现的原因,那么可以逐步排查代码
发现问题出在矩阵的快速幂里面
因为函数传n过去的时候指定的是int
而n本来应该是long long类型的
错误原因:这里的n传参写成了int
//矩阵的快速幂 //这里的n写成int类型有问题,这里要是long long Matrix pow(Matrix a, long long n) { Matrix ans, base = a; ans.row = 2; ans.column = 2; ans.v[1][1] = ans.v[2][2] = 1; while (n) { if (n % 2 == 1) ans = multiply(ans, base); base = multiply(base, base); n = n / 2; } return ans; }
3、完整斐波那契数列的矩阵快速幂解法
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 const int mod = 1000000007; 5 6 struct Matrix 7 { 8 //这里要用long long 9 long long v[3][3]; 10 int row, column; 11 Matrix() 12 { 13 memset(v, 0, sizeof(v)); 14 } 15 }; 16 17 //矩阵乘法 18 Matrix multiply(Matrix a, Matrix b) 19 { 20 Matrix ans; 21 ans.row = a.row; 22 ans.column = b.column; 23 for (int i = 1; i <= a.row; ++i) 24 { 25 for (int j = 1; j <= b.column; ++j) 26 { 27 for (int k = 1; k <= a.column; ++k) 28 { 29 ans.v[i][j] += (a.v[i][k] * b.v[k][j]) % mod; 30 ans.v[i][j] %= mod; 31 } 32 } 33 } 34 return ans; 35 } 36 37 //矩阵的快速幂 38 //这里的n有问题,这里要是long long 39 Matrix pow(Matrix a, long long n) 40 { 41 Matrix ans, base = a; 42 ans.row = 2; ans.column = 2; 43 ans.v[1][1] = ans.v[2][2] = 1; 44 while (n) 45 { 46 if (n % 2 == 1) 47 ans = multiply(ans, base); 48 base = multiply(base, base); 49 n = n / 2; 50 } 51 return ans; 52 } 53 54 int main() 55 { 56 long long n; 57 cin >> n; 58 Matrix a, last, ans; 59 a.row = 2; 60 a.column = 2; 61 a.v[1][1] = a.v[1][2] = a.v[2][1] = 1; 62 63 last.row = 2; 64 last.column = 1; 65 last.v[1][1] = last.v[2][1] = 1; 66 if (n == 1 || n == 2) 67 cout << 1 << endl; 68 else 69 { 70 ans = pow(a, n - 2); 71 ans = multiply(ans, last); 72 cout <<ans.v[1][1] << endl; 73 } 74 return 0; 75 }