题目描述
小红拿到了一个长为 n 的数组 a,定义数组中所有元素的乘积为 x。小红想知道,最大的满足 x 是 30 的 k 次方的倍数(形式化的,x \mod 30^k = 0)的 k 是多少?
题目链接:小红的k次方_牛客题霸_牛客网
输入格式
第一行输入一个整数 n (1≦n≦2×10^5)
第二行输入 n 个整数 ai (1≦ai≦10^9)
输出格式
输出一个整数,代表最大的 k
示例
输入
4
30 15 2 7
输出
2
问题分析
数据规模大:n 最大可达2×10^5 ,aᵢ 最大可达10^9
乘积极大:直接计算所有数的乘积会得到天文数字,远超任何数据类型的范围
需要高效算法:必须在 O(n) 或 O(n log n) 时间内解决问题
解题思路
第一步:数学转化
30 的质因数分解:
30=2×3×530=2×3×5
30 的 k 次方:
30^k=(2×3×5)^k=2^k×3^k×5^k
第二步:整除条件分析
设数组所有元素的乘积为 x,要使 x 能被 30^k 整除,即:
xmod 30^k=0
这意味着:
x 必须包含至少 k 个因子 2
x 必须包含至少 k 个因子 3
x 必须包含至少 k 个因子 5
第三步:得出关键结论
设数组所有数中:
因子 2 的总个数为 cnt_2
因子 3 的总个数为 cnt_3
因子 5 的总个数为 cnt_5
那么最大的 k 满足:
k≤cnt2 , k≤cnt3 , k≤cnt5
因此:
max k = min(cnt2,cnt3,cnt5)
第四步:算法设计
基于以上分析,我们不需要计算巨大的乘积 x,只需:
遍历数组中的每个数
统计每个数中因子 2、3、5 的个数
累加得到总个数
取三个总个数的最小值
代码实现
python
n=int(input()) arr=list(map(int,input().split())) a,b,c=0,0,0 for num in arr: while num%2==0: a+=1 num//=2 while num%3==0: b+=1 num//=3 while num%5==0: c+=1 num//=5 k=min(a,b,c) print(k)复杂度分析
时间复杂度
每个数需要被2、3、5整除若干次
对于每个数,循环次数最多为 log2 ai + log3 ai + log5 ai
总时间复杂度:O(n × log(max(a_i)))
对于 n (1≦n≦2×10^5),完全可行
空间复杂度
只需常数空间存储计数:O(1)
错误反思
错误1:直接计算乘积
问题:乘积 x 可能达到(10⁹)^{2×10⁵} = 10^{9 × 2×10⁵} = 10^{1.8×10⁶},远超任何数据类型范围。
错误2:二分查找法
虽然理论上可以用二分查找 k,但需要计算 30^k 和判断整除关系,同样面临大数问题,且效率不如直接统计。
总结
本题的核心在于:
数学转化:将整除问题转化为质因数统计问题
避免大数运算:通过统计因子个数代替实际计算乘积
理解整除的本质:a 整除 b 意味着 a 的所有质因子在 b 中都以足够的幂次存在
这种"避开直接计算,转为统计特征"的思路在算法竞赛中非常常见,特别是在处理大数、乘积、最大公约数等问题时非常有用。