【问题标题】:How to factorize a number?如何分解一个数字?
【发布时间】:2016-11-02 12:04:16
【问题描述】:

我被要求分解一个数字并以特定方式显示它。

例如:100 = 2^2*5^2

这是我目前使用的没有骰子的 C++ 代码,很遗憾:

#include <stdio.h>
#include <math.h> 

//IsPrime indicates whether a given number is or is not prime.
bool IsPrime(long long n)
{   
    int j = 3;
    if (n == 2)
    {
        return true;
    }
    else if (n % 2 == 0)
    {
        return false;
    }
    else
    {
        for (j = 3; j <= sqrt(n); j += 2)
        {
            if (n%j == 0)
            {
                return false;
            }
        }
    }
    return true;
}

int main(void)
{
    long long n_orig,n, i=3 , primecount=0;
    scanf("%lld", &n_orig);
    n = n_orig;
    if (n == 1)
    {
        printf("1");
        return 0;
    }
    if (IsPrime(n))
    {
        printf("%lld", n);
        return 0;
    }
    if (n % 2 == 0)
    {
        while (n >= 2 && n % 2 == 0)
        {
            primecount++;
            n = n / 2;
        }
        if (primecount == 1)
        {
            printf("2*");
        }
        else
        {
            printf("2^%lld*", primecount);
        }
    }
    primecount = 0;
    n = n_orig;
    while (i <= n/2)
    {
        if (IsPrime(i))
        {
            while (n >= i && n % i == 0)
            {
                primecount++;
                n = n / i;
            }
        }
        n = n_orig;
        if (primecount == 0)
        {
            i++;
            continue;
        }
        if (primecount == 1)
        {
            printf("%lld*", i);
        }
        else
        {
            printf("%lld^%lld*", i, primecount);
        }
        primecount = 0;
        i+=2;
    }
    printf("\b");
    return 0;
}

使用此代码,我能够生成一些测试用例,但是当我将答案上传到大概评估代码的网站时,在 7 个测试用例中(我不知道它们到底是什么),我通过 3fail 3在一个案例中超过时间限制(甚至没有在问题中声明的时间限制)。我真的很感激一些帮助,请对菜鸟友好!

另外,我真的不想知道我的答案是否可以通过某种方式改进,我现在的首要任务是了解为什么我自己的代码不能按预期工作。

P.S : iostreamarrays 的使用是不允许的。

提前致谢。

【问题讨论】:

  • 您在执行过程中是否使用调试器单步调试过您的代码?
  • 1 是素数吗? 0 是素数吗?
  • 你多久调用一次 sqrt 函数?
  • @CoryKramer 实际上我有,但当然是相对较小的数字,因为在跟踪大整数时可能需要相当长的时间。令人惊讶的是,我还没有遇到任何问题。
  • 使用j*j &lt;= n 而不是j &lt;= sqrt(n)

标签: c math


【解决方案1】:

试试这个:

#include <stdio.h>
#include <math.h>

unsigned long long PrintMultiplicity(unsigned long long n,unsigned long long factor)
{
    unsigned int count = 0;

    while (n%factor == 0)
    {
        count++;
        n /= factor;
    }

    if (count > 0)
    {
        printf("%llu^%u",factor,count);
        if (n > 1)
            printf("*");
    }

    return n;
}

void PrintFactorization(unsigned long long n)
{
    unsigned long long factor;
    unsigned int add;

    printf("%llu = ",n);

    n = PrintMultiplicity(n,2);
    n = PrintMultiplicity(n,3);

    // Check only factors that are adjacent to multiples of 6
    for (factor = 5, add = 2; factor <= sqrt(n); factor += add, add = 6-add)
        n = PrintMultiplicity(n,factor);

    if (n > 1)
        printf("%llu^1",n);

    printf("\n");
}

int main()
{
    unsigned long long n;
    scanf("%llu",&n);
    PrintFactorization(n);
    return 0;
}

【讨论】:

  • 谢谢!这似乎正在工作。不过有两个问题,请您解释一下 PrintFactorization 是如何工作的,而且我想知道我的程序似乎有什么问题,因为我的程序和您的程序似乎工作相似,至少对于一些测试用例。
  • @FuriousMathematician:我在行上方添加了一个注释,您可能会觉得难以理解。
  • 我猜add = 4-add 实际上应该是add = 6-add
  • @Henry:是的,很好的收获!会加快一点。感谢您指出这一点!!!
  • @barakmanos uhh ,我有点确定我开始看起来像个白痴,但我仍然无法弄清楚你正在使用的算法。 “与 6 相邻的因子”与什么有什么关系?
【解决方案2】:

您需要进行一些精细的优化。不要为每个值调用isPrime() 方法,而是考虑不同的方法,以便一开始就可以完全忽略不相关的值。

  1. 使用Sieve of Eratosthenes 概念获取n 下的相关素数列表。
  2. 从列表中的最低质数开始,除以n得到中间值

    n / lowest_prime_that_perfectly_divide_n

    通过检查下一个更高的质数继续执行此操作,直到 n 变为 1。这样,您将获得每个除法因子的 count

【讨论】:

  • 谢谢!我想这是必须要做的。
【解决方案3】:

您不需要素数测试,并且仅在加速时需要素数或素数轮的列表。列出所有主要因素的简单程序是

#include <stdio.h>
#include <math.h> 

int main(void)
{
    long long n_orig,n,k;
    scanf("%lld", &n_orig);
    n = n_orig;
    k=2;
    while(k*k<=n) {
        while(0==n%k) {
            n = n/k;
            printf("%lld ",k);
        }
        k++;
    }
    if(n>1) printf("%lld ",n);
    printf("\n");
    return 0;
}

这不会生成所需的输出格式,但可以很容易地添加到其中。

【讨论】:

  • 这会将k 增加到初始n 的最大素数。可以更早地停止(即当 k*k > n 时)。
  • 但是你必须单独处理可能剩余的大素数。完成。
  • 是的,但这是值得的。最坏情况的运行时间从 O(n) 到 O(sqrt(n))。 ;-)
猜你喜欢
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-25
  • 2018-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多