问题描述:
给出n个整数,请分解出它们的质因数。
输入格式:
第一行,一个整数n(n<=10000)
接下来n行,每行一个整数k(k<=2000,000,000,)
输出格式:
n行,每行代表一个整数的质因数,数字间以空格做间隔,按由小到大排列
样例输入:
3
100
1235
123456
样例输出:
2 5
5 13 19
2 3 643
题目分析:
这道题看上去不难,但是时间很少,优化时间的方法很值得一讲。
拿到题,相信大多数人都是这么写的:
#include<bits/stdc++.h>
using namespace std;
bool isprime(long long int num){
num = abs(num);
if(num == 2){
return true;
}
if(num%2 == 0 || num<2){
return false;
}else{
for(long long int i = 3; i*i <= num; i +=2){
if(num%i == 0){
return false;
}
}
return true;
}
}
int main ()
{
int n,k;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d",&k);
for(int j = 2; j <= k; j++){
if(k%j == 0){
if(isprime(j)){
printf("%d ",j);
}
}
}
printf("\n");
}
return 0;
}
前面是祖传判断质数函数,后面是主程序(啊~废话)
然而结果……
这时候,有大聪明就说了:
“质数都是奇数(2除外),所以我们只需要给2一个特判,在循环那里改为int j = 3; j <= k; j += 2不就行了?”
修改后代码:
#include<bits/stdc++.h>
using namespace std;
bool isprime(long long int num){
num = abs(num);
if(num == 2){
return true;
}
if(num%2 == 0 || num<2){
return false;
}else{
for(int i = 3; i*i <= num; i +=2){
if(num%i == 0){
return false;
}
}
return true;
}
}
int main ()
{
int n,k;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d",&k);
if(k%2 == 0){
printf("2 ");
}
for(int j = 3; j <= k; j += 2){
if(k%j == 0){
if(isprime(j)){
printf("%d ",j);
}
}
}
printf("\n");
}
return 0;
}
的却,这样要快一些,但不多……
除了空间加了4KB,其余还不如前面。
那怎么办呢?
举个例子:当输入2000000000(题目约定k的最大值)的时候,程序运行了很久,最终得出答案:2 5.
那么对应的优化方案就是找到一个因数后,不停地除以该因数,直到除不尽为止。
AC代码:
#include<bits/stdc++.h>
using namespace std;
bool isprime(long long int num){
num = abs(num);
if(num == 2){
return true;
}
if(num%2 == 0 || num<2){
return false;
}else{
for(long long int i = 3; i*i <= num; i +=2){
if(num%i == 0){
return false;
}
}
return true;
}
}
int main ()
{
int n,k;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d",&k);
if(k%2 == 0){
printf("2 ");
}
for(int j = 3; j <= k; j += 2){
if(k%j == 0){
if(isprime(j)){
printf("%d ",j);
}
//不停地除
while(k%j == 0){
k /= j;
}
}
}
printf("\n");
}
return 0;
}
这道题确实有意思,值得认真思考。