【问题标题】:Project Euler challenge 3: Finding the largest prime factor of a large number [duplicate]欧拉计划挑战 3:找到大数的最大素因数 [重复]
【发布时间】:2013-12-23 09:22:06
【问题描述】:

找不到投影仪 600851475143 的素数。我的代码成功地计算了测试数 13195 的最大素数以及我扔给它的每个测试数,但不知何故它会随着大素数而退化。你知道为什么吗?

#include <iostream>     
#include <queue>  
using namespace std;
int split(int split);
int largestprimefactor(priority_queue<int> myints);
int main()
{
int response = 2;
do{
    priority_queue<int> myints;
    int number;
    cout << "Please enter a number: ";
    cin >> number;
    myints.push(number);
    int lcf = largestprimefactor(myints);
    cout << endl << "Largest prime factor is: " << lcf;
    cout << endl << "Again?(1 for yes 2 for no): ";
    cin >> response;
}while(response == 1);
}
uint64_t split(uint64_t split)
{
if(split%2 != 0)
{
    if((split/2))%2 == 0)
        for(uint64_t i = (split/2)-1; i>1; i=i-2)
            if(split%i == 0)
                return i;
    else
        for(uint64_t i = (split/2); i>1; i=i-2)
            if(split%i == 0)
                return i;
    return 1;
}
else
    return 2;
}
int largestprimefactor(priority_queue<int> myints)
{
// largestfactor holds the next number to be tested for primeness in the queue
do{
    int largestfactor = myints.top();
    myints.pop();
    //splat will hold the first factor split finds of the top item in the queue
    int splat = split(largestfactor);
    //if it holds a 1 then that means that there are no factors
    if(splat != 1 && largestfactor)
    {
        myints.push(splat);
        myints.push(largestfactor / splat);
    }
    else
        return largestfactor;   
}while(myints.top() > 1);
}

【问题讨论】:

    标签: c++ algorithm


    【解决方案1】:

    您是否考虑过 600851475143 太大而无法存储在 32 位 int 中?

    查看您的编译器为 64 位整数类型提供了什么。

    【讨论】:

    • 我用 long 进行了尝试,得到了相同的答案,我的代码吐出 2147483647 除以 600851475143 时有余数 :(
    • @CodeManiak:您的系统上的 long 大小是多少?尝试 long long 或 uint64_t
    • 我的系统仍在处理数字...我会告诉你的!我可以听到处理器嗡嗡声...或硬盘驱动器。哪个嗡嗡声?风扇可能。也许我应该起来做一个三明治……天哪,我知道下次我使用 RSA 时我使用的是什么素数!
    • 问题 3 的一个好的解决方案没有理由不在一秒钟内运行,即使是在脚本语言中也是如此。也许你应该重新考虑你的方法(根据其他答案的 cmets)。
    • @CodeManiak 你是否将“每个”位置改为 long,而不仅仅是代码的开头?
    【解决方案2】:

    我可能无法帮助您优化代码(我不确定您在 split 中做了什么),但这里有一个想法。

    通过fundamental theorem of arithmetic,每个数字都有一个唯一的因式分解为素数的乘积。这意味着我们可以取一个数,然后将它依次除以其质因数,直到达到 1。最后一个质因数就是答案。

    现在,您只需要检查直到 sqrt(N) 的素数。注意,这并不意味着最大的素因数小于sqrt(N),而是如果有一个大于sqrt(N)的素因数,就有只有一个这样的主要因素。

    这导致了以下 O(sqrt(N)) 算法:

    long long largest_factor(long long number) {
        long long result = 0;
        for (long long i = 2; i * i <= number; ++i) {
            if (number % i == 0) {
                result = i;
                while (number % i == 0)
                    number /= i;
            }
        }
        if (number != 1)
            return number;
        return result;
    }
    

    在 600851475143 上运行它会给我正确的答案。

    【讨论】:

      【解决方案3】:

      600851475143 &gt;&gt; 32 给出 129,600851475143 &gt;&gt; 64 给出 3.10^-8。这个数字太大了,不能用 int 表示,但你可以用一个 long long 的 64 位数字来表示它,或者用一个类来表示更大的整数。

      【讨论】:

      • 不,因为 long long 小于 2^64。
      • 2^ 64 = 18446744073709551616 > 600851475143
      • @Толя 好的,你是对的。 codemaniak 的目标是让你实现一个高效的算法,这就是 project euler 的理念
      • 是的。如果您知道素数分解,则可以通过删除最小项来计算最大除数。 24 = (2^3) * 3,所以你知道你需要删除 2。顺便说一句,它很好,素数 + 分解在项目 euler 中重复出现,你可能想要重用你的代码。
      • @timday: 你需要为 Euler 实现一个筛子,但这个问题不需要筛子。然而,需要的是一些非愚蠢的分解算法。平方根的试除对于这个数字来说已经足够好了,然后有一些简单的改进可以将运行时间从几分之一秒降低到几分之一秒:-)
      猜你喜欢
      • 1970-01-01
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 2014-10-09
      • 2012-04-26
      • 1970-01-01
      相关资源
      最近更新 更多