微信扫一扫打赏支持

bug调试---1、斐波那契数列的矩阵快速幂解法bug

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 }

 

 

 

 

 

 
posted @ 2020-06-10 16:59  范仁义  阅读(267)  评论(0编辑  收藏  举报