前言
今天补发好久前的一篇,只因这一题困扰了我太久太久,不得不延期发布。不过好在最终找到了解决办法。
一,题目
二、难点
这一题要想出思路其实并不困难,但是问题就出在代码超时上。可以说,越简单的代码,依靠计算机循环枚举的次数就越多,就越容易超时;同时,也存在数据溢出(阶乘)的可能性。
例如我第一次的代码:
#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=k1,c++;a=k2,c++;……
到c=2时,a=k2=14>y.
printf结果是14,即14!为3773的倍数。
分析:
for语句用来进行第一次分类:
1.由不同质数乘起来——>n=k的最大非自身因数
2.存在多个相同质数相乘所得的因数——>进入do-while语句
do-while语句用来找到点2.中的n值
对n的要求:既是for循环所得k值的倍数,又在阶乘中包含i的值(因为i是初始k值的最大非自身因数)
总结
我太菜了呜呜呜