THUPC 2023 B题拧螺丝 简要题解

  • 本质构造

  • 通过二分答案,我们知道,在已知用多少块板的情况下,我们肯定是尽可能让螺丝均分

  • 这就告诉我们一个性质,木板上的螺丝只有两种可能, 要么是 \(Max\),要么是 \(Max - 1\)、、

  • 考虑倒推答案

  • 考虑维护一个三元组 \((x,y,z)\),表示当前最大值为 \(x\),最大值 \(x\) 个数为 \(y\), \((x - 1)\) 个数为 \(z\)

  • 显然答案就是从 \((x-k,2,0) \to (0,0,0)\) 所需要的转移次数

  • 考虑怎么转移(接下来就是平凡的讨论,自己画画图,就可以,难点在于要倒过来想):分两个情况, \(y \ge k\)\(y < k\)

  • 如果 \(y \ge k\),每次转移是

  • \(\begin{aligned} \\ \end{aligned}(x,y,z) \to (x - 1 - \frac{k-y}{y+z}, \\y + z + 1 - (k - y) \bmod (y + z),\\(k - y) \bmod (y + z))\)

  • (除法都是向下取整)

  • 转移是很好理解的,首先我们消耗 \(k - y\) 次把最大值的螺丝拔掉,然后剩下的均匀拔掉 \((y + z)\) 个板中的螺丝,然后再增加一个最大值让老板拿掉

  • (要注意每次拔完 \(k\) 个螺丝后,都要留一个最大值让老板拿掉 (!!!注意,题目中是老板先拿走一个木板后,你再接着转螺丝,但是我们让时光倒流了,所以是先拔完螺丝,再增加一个 (拔完后的最大值,注意是拔完后的最大值,不是拔完前的) ))

  • 然后 \(k < y\) 的情况就可以快速计算了,因为 \(k < y\) 的情况每个木板每次都只会拔一个钉子,(画个图模拟一下很容易看出转移方程)

代码如下:

import sys
sys.set_int_max_str_digits(100000)
n,k = map(int,input().split())
if k == 1:
    if (n == 1):
        print("1")
    else:
        print("Poor E.S.!")
elif k == 2:
    print(2**(n-2))
else:
    ans = 1
    x = n - k
    y = 2
    z = 0
    while (y <= k and x > 0):
        tmp = (k - y) // (y + z)
        mod = (k - y) - tmp * (y + z)
        x = (x - 1) - tmp
        y,z = (y + z + 1) - mod,mod
        ans += 1
    while (x > 0):
        x -= 1
        q = ((y - k) // (k - 1))
        y -= q * (k - 1)
        z += q * k
        ans += q
        # 整体处理
        if y == k:
            ans += 1
            y = k + z + 1
            z = 0
        else:
            ans += 2
            y -= (k - 1)
            z += k
            remain = k - y
            y = (y + z + 1) - remain
            z = remain
        # 处理边界情况

    print(ans)

posted @ 2023-03-06 18:03  y_dove  阅读(118)  评论(0编辑  收藏  举报