题目
Given any positive integer N, you are supposed to find all of its prime factors, and write them in the format
分析
题意是给出一个long int 型的整数,让我们按规定格式输出其质因子。
质因子其实就是素数,所以这是一道关于素数的应用。
素数的判断
我们先来回顾一下关于素数的判断,数学定义是“除了1和他本身能整除外,没有其他数能整除的整数”,因此代码可以用只要有除1和他本身能整除的数就排除的方法来写代码:
bool isPrime(int n)
{
if(n <= 1) return false;
int sqr = (int)sqrt(1.0 * n);
for(int i = 2; i <= sqr; i++)
{
if(n % i == 0) return false;
}
return true;
素数表的获取
有了素数的判断,规定号表长后,我们可以很轻易地获取一个素数表,如下,设prime[i] = 1为素数,prime[i] = 0则不是素数:
const int maxn = 101;
int prime[maxn] = {0}, pNum = 0;
void Find_Prime()
{
for(int i = 1; i < maxn; i++)
{
if(isPrime(i)) prime[i] = 1;
}
}
void Find_prime()
{
for(int i = 1; i < maxn; i++)
{
if(isPrime(i)) prime[Pnum++] = i;
}
}
上面是两种获取素数表的写法,第一种是利用哈希的思想,若表的坐标为素数则为1,反之为0;第二种是把素数按从小到大放入一个表里;两种方法均能快速取得素数。
进阶-更快的素数表(筛选)
上面获取素数表的方法是利用素数判断函数,然后逐个判断和写入,时间复杂度为O(n*n^(1/2)),接下来介绍一种更快的建立素数表方法——筛选法:算法从小到大枚举所有数,对每个数筛去他的倍数,那么剩下的就是素数啦!如2,则筛去4,6,8,10…等等,如此类推:
const int maxn = 101;
int prime[maxn] , pNum = 0;
bool p[maxn] = {0};
void Find_Prime()
{
for(int i = 2; i < maxn; i++)
{
if(p[i] == false)
{
prime[pNum++] = i;
for(int j = i + i; j < maxn; j += i)
{
p[j] = true;
}
}
}
}
以上算法没有用到素数判断函数,直接再筛是时候就把素数判断出来了,所以相比上一种方法省去了判断的操作,时间复杂度为O(n log log n)。
题目解答
//方法一:
//#include<cstdio>
//#include<cmath>
//
//const int maxv = 100010;
//
//bool is_prime(int n)
//{
// if(n == 1) return false;
// int sqr = (int) sqrt(n * 1.0);
// for(int i = 2; i <= sqr; i++)
// {
// if(n % i == 0) return false;
// }
// return true;
//}
//
//int Prime[maxv], num = 0;
//
//void Find_prime()
//{
// for(int i = 1; i < maxv; i++)
// {
// if(is_prime(i)) Prime[num++] = i;
// }
//}
//
//struct factor
//{
// int x, cnt;
//}fac[10];
//
//int main()
//{
// Find_prime();
// long int n; scanf("%ld", &n);
// int fac_num = 0;
// if(n == 1) printf("1=1");
// else
// {
// printf("%ld=", n);
// for(int i = 0; i < maxv; i++)
// {
// if(n % Prime[i] == 0)
// {
// fac[fac_num].x = Prime[i];
// fac[fac_num].cnt = 0;
// while(n % Prime[i] == 0)
// {
// fac[fac_num].cnt++;
// n /= Prime[i];
// }
// fac_num++;
// }
// if(n == 1) break;
// }
// if(n > 1)
// {
// fac[fac_num].x = n;
// fac[fac_num].cnt = 1;
// }
// for(int i = 0; i < fac_num; i++)
// {
// if(i > 0) printf("*");
// printf("%d", fac[i].x);
// if(fac[i].cnt > 1) printf("^%d", fac[i].cnt);
// }
// }
// return 0;
//}
方法二:
#include<cstdio>
#include<vector>
using namespace std;
vector<int> Prime(50000, 1);
int main()
{
for(int i = 2; i*i < 50000; i++)
{
for(int j = 2; j*i < 50000; j++)
{
Prime[i*j] = 0;
}
}
long int n; scanf("%ld", &n);
printf("%ld=", n);
if(n == 1) printf("1");
int status = 0;
for(int i = 2; i < 50000 && n > 1; i++)
{
int cnt = 0, flag = 0;
if(Prime[i] == 1 && n % i == 0)
{
if(status) printf("*");
while(n % i == 0)
{
cnt++;
n /= i;
flag = 1;
}
}
if(flag)
{
printf("%d", i);
if(cnt > 1) printf("^%d", cnt);
status = 1;
}
}
if(n > 1) printf("*%ld", n);
return 0;
}
以上便是用两种不同方法解答的代码,实测第一种方法耗时是第二种方法耗时的三倍以上,还等什么,赶紧试试吧!
小结
素数的应用归根结底就是构建素数表,利用素数表进行输出,而素数表的构建有两个方法,一是利用素数的判断函数,判断并写入表内;二是利用筛选法,剩下的即为素数算法进行写入。