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 }
来源:oschina
链接:https://my.oschina.net/u/4382640/blog/4307481