c ++中除数算法和的实现

时间:2015-10-24 17:29:06

标签: c++ algorithm

我试图在c ++中实现除数算法的总和,即

  

设n = p1 ^ a1 * p2 ^ a2 * .... * pk ^ ak

     

然后

     

σ(n)=((p1 ^(a1 + 1) -    1)/(p1-1))*((p2 ^(a2 + 1) - 1)/(p2-1))* ... *((pk ^(ak + 1) - 1)/(pk- 1))

将因子推入vector<int> p

的素数因子分解函数
void primeFactors(int n)
{
    while (n%2 == 0)
    {
        p.push_back(2);
        n = n/2;
    }
    for (ull i = 3; i <= sqrt(n); i = i+2)
    {
        while (n%i == 0)
        {
            p.push_back(i);
            n = n/i;
        }
    }
    if (n > 2)
        p.push_back(n);
}

然后我在vector<int> p中创建vector<int> pk的副本为vector<int> pk(p)并执行以下操作,以便在p中只包含唯一元素。

auto it = unique(p.begin(),p.end());
 p.resize(distance(p.begin(),it) );

现在最后按照公式获得总和:

for(int i=0;i<p.size();i++){
        sum *= (pow(p[i],count(pk.begin(), pk.end(), p[i]))-1)/(p[i]-1);
    }

上面的实现是错误的,因为我没有得到正确的输出。我哪里弄错了?他们是更好的实施方法吗?

1 个答案:

答案 0 :(得分:1)

计算结果的最后一个循环是pi^ai而不是pi^(ai+1)。将其更改为:

for (int i = 0; i < p.size(); i++){
    sum *= (pow(p[i], count(pk.begin(), pk.end(), p[i]) + 1) - 1) / (p[i] - 1);
}

还有一件事,而不是使用向量并使用uniquecount,您只需使用map<int, int>而不是在O(n)中获取每个素数的出现次数)在O(lgn)中得到它:

void primeFactors(int n, map<int, int> &facs){
    facs.clear();
    for (long long p = 2; p*p <= n; p++){
        while (n%p == 0){
            facs[p] ++;
            n /= p;
        }
    }
    if (n > 1)
        facs[n] = 1;
}

long long getRes(map<int, int> &facs){
    long long t, res = 1;
    for (auto it = facs.begin(); it != facs.end(); ++it){
        t = pow(it->first, it->second + 1) - 1;
        t /= (it->first - 1);
        res *= t;
    }
    return res;
}

在上面的代码中,我还使用pow函数来计算结果。我们可以通过在地图中存储功率值而不是计数来消除此功能,如下所示:

void primeFactors(int n, map<int, long long> &facs){
    facs.clear();
    for (long long p = 2; p*p <= n; p++){
        while (n%p == 0){
            if (facs.count(p))//this way we can save pi^(ai+1) instead of counting prime numbers
                facs[p] *= p;
            else
                facs[p] = p*p;
            n /= p;
        }
    }
    if (n > 1)
        facs[n] = n*n;
}

long long getRes(map<int, long long> &facs){
    long long t, res = 1;
    for (auto it = facs.begin(); it != facs.end(); ++it){
        t = it->second - 1;  //this is for pi^(ai+1)-1
        t /= (it->first - 1);
        res *= t;
    }
    return res;
}