10_20 阶乘倍数


前言

今天补发好久前的一篇,只因这一题困扰了我太久太久,不得不延期发布。不过好在最终找到了解决办法。


一,题目

在这里插入图片描述

二、难点

这一题要想出思路其实并不困难,但是问题就出在代码超时上。可以说,越简单的代码,依靠计算机循环枚举的次数就越多,就越容易超时;同时,也存在数据溢出(阶乘)的可能性。
例如我第一次的代码:

#include <stdio.h>
int prime(long long n) {
    long long i = 2 ;
    while (i * i < n) {
        if (n % i == 0) 
            return 0;
        else
            i++;
    }
    return 1;
}

long long fac(long long n) {
    long long i = 2, k = 1;
    while (i <= n) {
        k *= i;
        i++;
    }
    return k;
}

int rem(long long a, long long b) {
    if (a < b) {
        int c = a;
        a = b;
        b = c;
    }
    int r = a;
    while (a % b != 0) {
        r = a % b;
        a = b;
        b = r;
    }
    return b;
}

int main() {
    long long k = 0;
    scanf("%lld", k);
    long long n = 2;
    if (prime(k) == 1)
        printf("%lld", k);//如果k是质数,那么k之前不会出现k的因数,也就不可能阶乘等于k
    else 
    {
        while (fac(n) % k != 0) 
        {//当n的阶乘不是k的倍数
            n++;
        }
        printf("%lld", n);
    }
    return 0;
}

然后这是我的电脑给我的答复
在这里插入图片描述
不知有没有大佬知道是怎么一回事呜呜呜呜

感谢同校的CSDN博主「二分之无丌」给出的答案,拨云见日,成功的解决了我的问题,以下转载于二分之无丌
在这里插入图片描述
我对他在CSDN中所写的第二点的理解是,对于任意一个数,它除自己外的最大因数的阶乘一定是它的倍数,所以为了减少循环跑的次数,同时防止阶乘溢出,可以对k采用边

#include<stdio.h>
#include<math.h>
int main()
{
    long long k,s,y=1,a=1,c=1;
    scanf("%lld",&k);
    s = sqrt(k);
    for(long long i=2;i<=s;++i)
    {
        if(k%i==0)//如果i是k的一个因数
        {
            k /= i;
            y = i;
        }
        if(k==1)//即k已经除完了它所有的因数
        {
            printf("%lld",i);//由于i是逐一递增,此时它的值就是k的最大因数(除去k自己)
            return 0;//main函数结束
        }
    }//如果出了for循环,说明k经过循环后是个质数,且此时i>k,且i是初始k的最大非自身因数       //(否则k将仍能分解,不是质数)
     //且说明k的一个因数由多个相同质数相乘而成
    do
    {
        a=k*c;
        c++;
    }
    while(a<=y);
    printf("%lld",a);
    return 0;
}
————————————————
版权声明:本文为CSDN博主「二分之无丌」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_71919496/article/details/133515219

例如117^3=3773,在for循环中i=7和11时进入if(k%i==0)语句,之后出循环。
此时k=49,y=11
进入do-while语句,a=k
1,c++;a=k2,c++;……
到c=2时,a=k
2=14>y.
printf结果是14,即14!为3773的倍数。
分析
for语句用来进行第一次分类:
1.由不同质数乘起来——>n=k的最大非自身因数
2.存在多个相同质数相乘所得的因数——>进入do-while语句
do-while语句用来找到点2.中的n值
对n的要求:既是for循环所得k值的倍数,又在阶乘中包含i的值(因为i是初始k值的最大非自身因数)


总结

我太菜了呜呜呜

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值