(每日一练)题目名称:凑数

文盲老顾
WEB应用领新星创作者
博客专家认证
2023-06-08 17:44:28

给定一组n个正整数,要求每次选其中一个数乘以或除以一个素数(称为一次凑数),问至少需要凑数多少次可以把所有的数都凑成相等。

可以把所有的数都凑成相等需要至少进行的凑数次数t(t>=0)。

周赛57期的新题目,当时没能 ac ,然后,今天随便弄了弄,居然 ac 了,但不明白为什么 ac 的,呵呵

arr = list(map(int,input().split()))
n,m = len(arr),int(max(arr) ** .5 + 1)
ans = 0
for i in range(2,m):
    z = []
    for j in range(n):
        c = 0
        while arr[j] % i == 0:
            c += 1
            arr[j] //= i
        z.append(c)
    ans += sum(z) - min(z) * n
print(ans + n - arr.count(1))
...全文
175 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
请叫我问哥 2023-06-08
  • 打赏
  • 举报
回复

其中有个测试用例是 [934906, 869814, 593826, 642589, 904024, 572674, 718422, 812732, 873256, 582947]
能AC的答案是38次,也就是所有数字都向下除,全变成1。
但我的代码得到的是32次,即全变成2(其中奇数除到1后再乘以2)
由此可见,C站的“标准答案”似乎只考虑了除法,并没有考虑乘法可能更优。

请叫我问哥 2023-06-08
  • 打赏
  • 举报
回复

此题是好题,但从结果来看,题意描述有很大的问题,如果“凑数”表示可乘也可除,那么最短“距离”应该是每个素数个数到其中位数的距离之和。但从结果来看,能AC的代码却是到每个素数个数最少的个数距离之和,显然并不是最优的。
我实现的代码如下,只要将循环改写成注释部分就能AC了,但我并不相信C站,所以我还是坚持自己,除非有人能说服我 :D

from collections import defaultdict

def fun(n):
    cnt = 0
    if n % 2 == 0:
        while n % 2 == 0:
            cnt += 1
            n //= 2
        factors[2].append(cnt)
    for i in range(3, int(n**0.5)+1, 2):
        if n % i == 0:
            cnt = 0
            while n % i == 0:
                cnt += 1
                n //= i
            factors[i].append(cnt)
    if n > 2: factors[n].append(1)

factors = defaultdict(list)
for n in arr: fun(n)
m = len(arr)//2 + 1
res = 0
for f in factors.values():
    f.sort()
    p = len(f) - m
    if p >= 0: 
        res += sum(abs(f[p]-i) for i in f) + (len(arr)-len(f))*f[p]
    else: 
        res += sum(f)
    # if len(f) == len(arr):
    #     res += sum(f) - min(f)*len(arr)
    # else:
    #     res += sum(f)
print(res)

321

社区成员

发帖
与我相关
我的任务
社区描述
主要用于技术交流,包括但不限于 .net,mssql,js,css,python,算法,运维。也可以晒最新技术,美图,运动等。最后,如果有问题,可以提问,老顾能帮忙的会尽量帮忙哦。
前端sqlserverasp.net 技术论坛(原bbs) 北京·西城区
社区管理员
  • 文盲老顾
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧