题目描述
难度分:1400
输入T(≤104)表示T组数据。
每组数据输入n(1≤n≤109)和m(1≤m≤109)。
输出n,2n,3n,…,mn中末尾零最多的数。如果有多个符合要求的数,输出其中最大的。
输入样例
10
6 11
5 43
13 5
4 16
10050 12345
2 6
4 30
25 10
2 81
1 7
输出样例
60
200
65
60
120600000
10
100
200
100
7
算法
枚举
根据数据范围,230>109,513>109。考虑到某个数的尾随零个数取决于它因子2个数和因子5个数的较小值,因此对于给定的n,我们可以先在O(logn)的复杂度下求出n中的因子2个数cnt2,n中的因子5个数cnt5。然后枚举因子2和5的个数i和j,对于2i×5j≤m的(i,j):
- 如果min(cnt2+i,cnt5+j)变大了,直接更新答案为n×⌊m2i×5j⌋×2i×5j。
- 如果min(cnt2+i,cnt5+j)不变,就只有在n×⌊m2i×5j⌋×2i×5j比当前答案大时才更新答案。
其中⌊.⌋表示对.向下取整,之所以要用m除以2i×5j,就是为了在n的倍数k包含足够尾随零且kn≤m的情况下能够得到更大的数。
复杂度分析
时间复杂度
每个case需要先计算n中因子2和因子5的数量,时间复杂度为O(log2n+log5n)。然后双重循环枚举m中因子2和因子5的数量,时间复杂度为O(log2mlog5m),大概为O((logm)2)。T个case总的时间复杂度为O(T(logn+(logm)2))
空间复杂度
仅使用了有限几个变量,额外空间复杂度为O(1)。
python代码
t = int(input())
for _ in range(t):
n, m = map(int, input().split())
x = n
cnt2, cnt5 = 0, 0
while x % 2 == 0:
x >>= 1
cnt2 += 1
while x % 5 == 0:
x //= 5
cnt5 += 1
ans = 0
cnt = min(cnt2, cnt5)
for i in range(31):
for j in range(14):
num = 2**i*5**j
if num <= m:
res = m//num*num*n
if cnt < min(cnt2 + i, cnt5 + j):
cnt = min(cnt2 + i, cnt5 + j)
ans = res
elif cnt == min(cnt2 + i, cnt5 + j):
if res > ans:
ans = res
if cnt == 0:
ans = n*m
print(ans)