时间限制: 1000 Sec 内存限制: 128 MB
题目描述
已知正整数n是两个不同的质数的乘积,试求出两者中较大的那个质数。
输入
输入只有一行,包含一个正整数n。
输出
输出只有一行,包含一个正整数p,即较大的那个质数。
样例输入
21
样例输出
7
提示
【数据范围】
n <= 2*109
来源/分类
NOIP普及
解题思路
- 由于n的值达到10的9次方量级,因此以下做法是低效的,估计会超时。这一做法是:令p依次取3, 5, 7, 9, 11, 13, 15, …, n \sqrt{n} n,看p和q(=n / p)是否符合要求。
- 假设p和q是一组解,有q=n/p,且有q > n,那么必有:p <= n \sqrt{n} n,q>= n \sqrt{n} n。
- 解题思路是:
(1)从小到大地,利用筛选法找出 n \sqrt{n} n内的全部质数p,存入prime_set。每找到一个质数p,如果n整除p,则把候选解 (p, q)追加到houxuan_list尾部,这里q = n / p。
(2)从左到右遍历候选解列表houxuan_list,对于候选解(p, q),如果q是质数,那么q就是题目要求的结果。
(3)如何判断q是否是质数?答案是,让q依次除以prime_set中的每个质数,如果整除某个质数,那么不是;都不能整除,那么是质数。 - 关于筛选法求质数(即素数)的做法,网上有大把的讲解,这里不予赘述。
参考答案
#num是质数吗
#prime_set里头保存了num的平方根内的全部素数
import math
def is_prime(num, prime_set):
num_sqrt = int(math.sqrt(num))
for p in prime_set:
if num % p == 0:
return False
return True
#把i的奇数倍数(不大于n_sqrt)加入非质数集合not_prime_set
def add_not_prime_set(not_prime_set, i, n_sqrt):
for m in range(3, n_sqrt + 1, 2):
not_prime_set.add(m * i)
n = int(input())
if n % 2 == 0:
print(n // 2)
else:
n_sqrt = int(math.sqrt(n))
#找出1到n_sqrt之间的质数和非质数
not_prime_set = set()
prime_set = set()
houxuan_list = [] #保存候选解
for i in range(3, n_sqrt + 1, 2):
if i not in not_prime_set:
prime_set.add(i)
#把i的倍数加入not_prime_set
add_not_prime_set(not_prime_set, i, n_sqrt)
if n % i == 0:
houxuan_list.append((i, n // i))
for lessone, largerone in houxuan_list:
if is_prime(largerone, prime_set):
print(largerone)
break
测试用例
-
n是偶数的情形
样例输入
1994
样例输出
997 -
n是奇数的情形。
样例输入
2991
样例输出
997 -
n是奇数的情形。n稍大一点。结果不是997。
样例输入
8767
样例输出
797
小结
- 这道题要关注时间开销。对于n为109的量级的题目,只能采用线性级别(即时间开销为O(n))的算法。
- 筛选法求质数比较常用,值得熟练掌握。