问题描述
试题编号: | 202312-2 |
试题名称: | 因子化简 |
时间限制: | 2.0s |
内存限制: | 512.0MB |
问题描述: | 题目背景质数(又称“素数”)是指在大于 1 的自然数中,除了 1 和它本身以外不再有其他因数的自然数。 问题描述小 P 同学在学习了素数的概念后得知,任意的正整数 n 都可以唯一地表示为若干素因子相乘的形式。如果正整数 n 有 m 个不同的素数因子 p1,p2,⋯,pm,则可以表示为:n=p1t1×p2t2×⋯×pmtm。 小 P 认为,每个素因子对应的指数 ti 反映了该素因子对于 n 的重要程度。现设定一个阈值 k,如果某个素因子 pi 对应的指数 ti 小于 k,则认为该素因子不重要,可以将 piti 项从 n 中除去;反之则将 piti 项保留。最终剩余项的乘积就是 n 简化后的值,如果没有剩余项则认为简化后的值等于 1。 试编写程序处理 q 个查询:
输入格式从标准输入读入数据。 输入共 q+1 行。 输入第一行包含一个正整数 q,表示查询的个数。 接下来 q 行每行包含两个正整数 n 和 k,表示一个查询。 输出格式输出到标准输出。 输出共 q 行。 每行输出一个正整数,表示对应查询的结果。 样例输入 Data 样例输出 Data 样例解释查询一:
查询二:
查询三:
子任务40% 的测试数据满足:n≤1000; 80% 的测试数据满足:n≤105; 全部的测试数据满足:1<n≤1010 且 1<k,q≤10。 |
分析:求素数是一个很经典的题型。考虑到题目中所给的范围很大,用一般的方法来求(遍历模到开根号),复杂度比较大,为了避免多余的复杂度,使用复杂度为n的筛选法,来求以内的素数,最大到。然后再进行其他操作。
一开始,我想的是“去掉不要的”,即把原始n除素数,发现要保留,再复原回来,但是这样的通过率只有80%。代码如下:
#筛选法记录素数
max_val = 100001
is_prime = [1] * max_val
primes = []
for i in range(2,max_val):
if is_prime[i] == 0:
continue
primes.append(i) # 记录好素数
j = 2
while( i*j < max_val ):
is_prime[i*j] =0
j+=1
q = int(input())
for _ in range(q):
n , k = map(int ,input().split())
for i in range(len(primes) ):
num = 0
if n% primes[i] == 0:
while(n%primes[i] == 0):
num += 1
n //= primes[i]
if num >= k:
n *= pow(primes[i],num) # 复原
print(n)
很抽象,感觉是完全没有问题,于是小摆一下。
又想到,如果复原不行,累乘行不行。也就是说,复原是复原需要的,去除不要的;那么累乘就是:完全不考虑不要的,只乘上需要的。
代码如下:
#筛选法记录素数
max_val = 100001
is_prime = [1] * max_val
primes = []
for i in range(2,max_val):
if is_prime[i] == 0:
continue
primes.append(i) # 记录素数
j = 2
while( i*j <= 100000):
is_prime[i*j] =0
j+=1
q = int(input())
for _ in range(q):
n , k = map(int ,input().split())
result = 1
for i in range(len(primes) ):
num = 0
if n% primes[i] == 0:
while(n%primes[i] == 0):
num += 1
n //= primes[i]
if num >= k:
result *= pow(primes[i],num) # 累乘
print(result)
答案莫名奇妙的对了。