牛客优质好题分析(1)-----质数因子(合数思想)(C语言写法)

题目:
在这里插入图片描述
点击:质数因子

本题我写了几种方法,由浅入深
看答案,让我们先分析一下题目,这个题目说的是给你一个数,让你用他的质因子表示出来,比如180=2 * 2 * 3 * 3 * 5
那么让我们先了解一个概念合数

合数是合数是指整数中除了能被1和本身整除外,还能被0除外的其他数整除的数
也就是说大于2的数不是质数就是合数
那么一个合数是不是就可以通过它的最小质因子乘以一个合数呢?
所以我们现在用大写字母表示合数,小写字母表示最小质因子,则A=a * B,那么这个B=A/a,
然后B=b * C,那么这个C=B/b,以此类推当,都是质因子的时候就拆解结束了
于是A=a * b * c * d…(任何一个合数都可以用一个素数与一个更小的合数的积表示,然后递归定义 )
根据这个原理可知一个合数的最小因子一定是它的最小质因子,因为它的因子(母体的因子)要么是质数要么是合数(不是母体),而合数还可以拆解成质数,因为这个合数(不是母体)是原本那个合数的因子(母体),而它拆解的质数是这个合数(不是母体)的因子,所以这个质数一定也是原来那个合数(母体)的因子,所以总的来说一个合数可以拆成很多因子,而这些因子一定是由它的质因子构成的,所以结论成立,这段文字不太说的明白,你记住就行,可以多看几遍!!
ps:母体就是最开始的合数A

看代码

int main()
{
    int num, k, i = 0;
    scanf("%d", &num);
    for (k = 2; k <= num; k++)
    {

        while (num % k == 0)
        {
            printf("%d ", k);
           num/=k;
        }
    }
    return 0;
}

这里的num/=k其实就是求下一次的合数(B)
程序当num=1就结束了
由于一个合数的最小因子一定是它的最小质因子
所以这个num % k == 0是行的通的,这个k就是最小因子,那么也就是最小质因子喽
就这样循环

其实一开始我也没想到,一开始的代码我给你们看看(老脸豁出去啦)

#include<stdio.h>
int isprime(int i)
{
    int count = 0;
    for (int j = 1; j <= i; j++)
    {
        if (i % j == 0)
            count++;

    }
    if (count == 2)
        return i;
    else
        return 0;
}
int main()
{
    long num = 0;
    scanf("%d", &num);
    while (num != 1)
    {
        for (int k = 1; k <= num; k++)
        {
            if (num % k == 0)
            {
                if (isprime(k))
                {
                    printf("%d ", k);
                    num /= k;
                    break;

                }
            }
        }
    }
    return 0;
}

现在看来,那个判断素数的步骤是不是多此一举啦!

但是我们发现改过的代码数据还是不能都过
在这里插入图片描述
代码其实没有错,就是运行时间超了,那我们一个优化一下!!
我们得知道一个合数的最小质因子不会超过它的开根号+1的
我们证明一下:

一个合数如果有超过两个因子的话
我们假设这个合数为n,因子为p[i],最小因子(最小质因子,上面提到过)为p
那么n=p[1]*p[2]p[3]…
那么p<=p[2],这个能理解吧,我们这里说的所有因子都是从小到大哦
于是根据不等式p
p<=p[1]*p[2]<=p[1]*p[2]*p[3]…=n
那么p<=sqrt(n)
这不就证明出来了嘛

看优化后的代码:

int main()
{
    int num, k, i = 0;
    scanf("%d", &num);
    for (k = 2; k <= num; k++)
    {
			 //最小质数因子必小于输入数字的平方根
        if (k > sqrt(num) + 1)
        {
             k= num;
        }
        while (num % k == 0)
        {
            printf("%d ", k);
           num/=k;
        }
    }
    return 0;
}

这优化了遍历的次数
我们的中心思想是什么??我们要获取最小质因子k啊,当我们找到了所有的质因子后,我们就不需要在循环了呀,那我们该怎么操作?、
于是就优化了!!
k在不停的加,而num在不停的减小,他们之间有着一层关系就是 (k<=sqrt(num)) 一旦打破这层关系,我们就不需要循环了,不优化前他就还在循环!!

可能博主说的有点麻烦,但是只要读者能看懂,那我就心满意足啦!!

这个合数的思想也用于欧拉筛法哦

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

相知-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值