卡在下面的dp代码中

时间:2017-06-06 14:22:09

标签: c++ algorithm dynamic-programming prime-factoring

我编写了以下dp代码来查找数字的素数因子。

#include <bits/stdc++.h>
#define max 1000001
using namespace std;
vector <int> prime;
vector<bool> isprime(max,true);
vector<bool> visited(max,false);
vector<int> data(max,-1);
void dp(int n,int last)
{
    if(n >= max || visited[n])
        return;
    visited[n] = true;
    for(int i = last;i<prime.size();i++)
    {
        if(n*prime[i] >= max || data[n*prime[i]] != -1)
            return;
        data[n*prime[i]] = prime[i];
        dp(n*prime[i],i);
    }
}
int main()
{
    isprime[1] = false;
    data[1] = 1;
    for(int i = 4;i<max;i += 2)
        isprime[i] = false;
    for(int i = 3; i*i< max;i += 2)
    {
        for(int j = i*i; j < max;j += i)
            isprime[j] = false;
    }
    prime.push_back(2);
    data[2] = 2;
    for(int i =3;i<max;i += 2)
        if(isprime[i])
        {
            prime.push_back(i);
            data[i] = i;
        }

    for(int i = 0;i<prime.size();i++)
    {
        dp(prime[i],i);
    }
        cout<<"...1\n";
    for(int i = 2;i<=8000;i++)
    {
        cout<<i<<" :- ";
        int temp = i;
        while(temp!= 1)
        {
            cout<<data[temp]<<" ";
            temp = temp/data[temp];
        }
        cout<<endl;
    }

    return 0;
}

此处,last是素数n的最后一个索引。 但是我为此获得了分段错误,当我将max更改为10001时,它运行得非常完美。我不知道为什么会发生这种情况,因为使用的数据结构是1-d向量,可以容易地保存最多10 ^ 6的值。

1 个答案:

答案 0 :(得分:1)

我使用GDB检查了你的程序。分段错误发生在这条线上:

if(n*prime[i] >= max || data[n*prime[i]] != -1)

在您的for循环中第一次调用DP时,调用dp(2,0),递归调用最终会生成此调用:dp(92692,2585)。

92692 * 2585 = 239608820

这个数字大于32位整数可以容纳,因此这两个数字的整数乘法产生的r值溢出并变为负数。 nprime [i]变为负数,因此上述循环的第一个条件失败,第二个条件被检查。访问data [n * prime [i]],由于n * prime [i]为负数,程序将访问无效内存和段错误。要解决此问题,只需在参数列表中将n更改为long long,就可以了。

void dp(long long n, int last)