蓝桥杯试题集试题总汇(C++)
问题描述
给定一个正整数n,尝试对其分解质因数
输入格式
仅一行,一个正整数,表示待分解的质因数
输出格式
仅一行,从小到大依次输出其质因数,相邻的数用空格隔开
样例输入
100
样例输出
2 2 5 5
数据规模和约定
n<=2147483647
分析
这道题思路对学编程的来说应该是很简单的,但很多代码大多都是运行超时。为了避免超时我们必须想尽一切办法优化我们的代码。以下是我考虑的方面:
1.如果输入的值是质数,那它就没有质因数可求了,质数的质因数只有其本身,所以直接输出,避免求解运行时间。
2.是如何求其质因数,这里我借用了一位大佬的代码,就是一个数在从2开始判断是否为其质因数,如果是就除尽2的因数,那么接下来循环能被除尽2的数的整除的数,那么这个数也是原数的质因数,一次类推。例如输入的数n=100,那么从2开始判断是否是100的质因数,明显2是100的质因数,那么就一直除以2,100/2=50,50/2=25,直到不能整除为止(代码以取余判断是否为整除),接下来继续进行循环,此时n=25不能整除3,4,跳到了5。25/5=5,那么5也是100的质因数。接着25/5=5,5/5=1,1/5不是整除。此时n=1<i=5,for循环条件不满足,就结束循环了。
3.我认为也是解决运行超时问题的关键代码。首先我们要意识到,一个数在除过他的质因数后,一定是质数或者是1。我们可以判断每次除尽一个质因数后的数是否是质数(另外判断质数函数包含了1返回ture),如果是直接输入、返回,就不需要再次进行多余的循环判断。比如输入的是100,除尽他的质因数2,2,5,5后,剩下的n就变成1了。再比如输入的是2000000014,首先代码会输出2,之后n就变成了1000000007,我们对1000000007进行质数判断,如果是的话就直接输出,返回。避免了对1000000007求其质因数的巨大运行消耗。
4.另外我在判断质数的时候也进行了优化:首先在判断质数的时候,可以先去除偶数,因为偶数都是都不是质数(除了2),然后for循环的终止条件设为i<=sqrt(n),i+2以减少循环。
参考代码
#include<iostream>
#include<math.h>
using namespace std;
bool zhishu(int n)//质数判断
{
if(n==2)
return true;
if(n%2==0)
return false;
for(int i=3;i<=sqrt(n);i=i+2)
{
if(n%i==0)
return false;
}
return true;
}
int main()
{
int n;
cin>>n;
if(zhishu(n))//直接对输入值进行质数判断,如果是输出的数据本身是质数直接返回
{
cout<<n;
return 0;
}
for (int i = 2; i<= n; i++)
{
if (n % i == 0)
{
while(n % i == 0)//完全筛去i因子,确保下一个得到的是n的素因子,
{ //对于这一步是我在其他博主上看到的一段很牛的代码,但具体原理我不是很懂。
cout<<i<<" ";
n = n / i;
}
}
if(zhishu(n))//这是避免运行超时的重要一步,
//在筛选一次质因子后,就直接判断除去的质因数的数是否是质数,
//如果是质数直接输出,就不必要进行之后多余的判断。
{
cout<<n;
return 0;
}
}
}
备注:
对于 for 循环中,为什么不对 i 判断是否为素数,难道不会出现 i 为合数时,满足 n % i == 0,从而输出合因数吗?答案是不会的,比如到 i =4,因为之前已经全部把含 2 的素因数提出来,之后的 n 不再有 2 的因数,所以也不会再出现 n % 4 == 0,比如 i = 6 ,由于已经把含 2 , 3 可能的素因数提取出来,所以 n % 6 !=0。之后的8,9,10,12……都是这样的道理。你品,你细品。