微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

分解为质因数

如何解决分解为质因数

所以我遇到了一个我似乎无法解决的问题。我想显示因子和它被提升到的功率(基本上是质因子分解),我已经在 python 中完成了这个,但由于某种原因我不能在 C 中实现它,这就是我想出的

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

int main()
{
    int i = 2,p,c,n;
    scanf("%d",n);
    while (n > 9)
    {
        p = 0;
        c = 1;
        while (n % i == 0)
        {
            for (int d = 2; d <= i / 2 + 1; d++)
                if (i % d == 0 && i % 2 != 0)
                    c = 0;
            if (c == 1)
            {
                p = p + 1;
                n = n / i;
            }
            if (p != 0)
            {
                printf("%d %d",i,p);
                printf("\n");
            }
            i = i + 1;
        }
    }
    return 0;
}

解决方法

问题 #1(虽然这不是您的主要问题)是您在 scanf 调用中缺少一个指针:

scanf("%d",n);

必须的

scanf("%d",&n);

(我的编译器立即警告我这一点。不知道为什么你的没有。)

问题 #2 是 while (n > 9) 完全错误。我想你想要while (n > 1)

问题 #3 是 i = i + 1 步骤放错了位置。无论 i 是否是一个因素,您都需要这样做,因此它需要位于最外层循环的末尾。

然后问题#4 是以

开头的代码
for (int d = 2; d <= i / 2 + 1; d++)

看起来您正在尝试检查 i 是否为质数,尽管您这样做为时已晚:您已经在 if 中测试是否 in 的因数。此外,您没有适当的循环来计算 in 的因数的次数。

但事实证明,您实际上并不需要测试 i 是否为素数,所以让我们暂时将素数测试步骤搁置一旁,看看会发生什么.

这是第一个固定版本:

#include <stdio.h>

int main()
{
    int i = 2,p,n;
    scanf("%d",&n);
    while (n > 1)
    {
        if (n % i == 0)           /* if i is a factor */
        {
            p = 0;  
            while (n % i == 0)    /* count how many times i is a factor */
                {
                n /= i;
                p++;
                }
        printf("%d %d\n",i,p);
        }

        i++;
    }
    return 0;
}

这有效!它尝试了 i 的所有可能值,这是非常低效的,但由于质因数分解的特性,这没关系。它会按顺序尝试它们,因此它总是首先清除所有较低的素数因子,因此没有一个非素数 i 将通过打印为一个因子。

为了做我猜你想要做的事情,我们必须重新排列代码。基本算法是:对于每一个i,如果是素数,看它把运行中的n整除多少次。

#include <stdio.h>

int main()
{
    int i = 2,c,&n);
    while (n > 1)
    {
        /* see if i is prime */
        c = 1;
        for (int d = 2; d <= i / 2 + 1; d++)
            if (i % d == 0 && i % 2 != 0)
            {
                c = 0;
                break;
            }

        if (c == 1)                /* if i is prime */
        {
            p = 0;
            while (n % i == 0)     /* count how many times i is a factor */
            {
                p = p + 1;
                n = n / i;
            }

            if (p != 0)
                printf("%d %d\n",p);
        }
        i = i + 1;
    }
    return 0;
}

素性测试仍然很粗糙(if (i % d == 0 && i % 2 != 0) 行很可疑),但它似乎有效。不过,我怀疑这仍然很浪费:如果您生成所有可能的试验除数来分解 n,那么可能有比从头开始对每个 i 运行完整素性测试更好的方法。

一种流行的快捷方式是让 i 遍历 2,3,5,7,9,11,13,...(即 2 加上所有奇数)。基于这个想法,我曾经写过一些代码,它使用更复杂的增量序列,因此它最终使用 2、3、5,然后是每个不是 3 或 5 倍数的奇数。我怀疑(但是我还没有测量过)浪费地使用一些非质数的试验除数 i 可能比肯定地确认每个试验除数是严格质数的浪费更少。

但是,如果您真的关心效率,您将不得不放弃这种盲目尝试所有试除数的明显但仍然相当暴力的技术,而转向更复杂的方法,例如 elliptic curve factorization。我们在这里做的是 trial division,正如维基百科所说,它是“最费力但最容易理解的 integer factorization 算法”。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。