結果

問題 No.1782 ManyCoins
ユーザー 草苺奶昔草苺奶昔
提出日時 2024-09-08 23:01:32
言語 Python3
(3.12.2 + numpy 1.26.4 + scipy 1.12.0)
結果
TLE  
実行時間 -
コード長 5,924 bytes
コンパイル時間 373 ms
コンパイル使用メモリ 12,928 KB
実行使用メモリ 73,552 KB
最終ジャッジ日時 2024-09-08 23:01:55
合計ジャッジ時間 13,186 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 37 ms
18,720 KB
testcase_01 AC 65 ms
12,160 KB
testcase_02 AC 37 ms
11,904 KB
testcase_03 AC 36 ms
11,776 KB
testcase_04 AC 39 ms
11,776 KB
testcase_05 AC 36 ms
11,776 KB
testcase_06 AC 37 ms
11,776 KB
testcase_07 AC 37 ms
11,776 KB
testcase_08 AC 38 ms
11,776 KB
testcase_09 AC 36 ms
11,776 KB
testcase_10 AC 38 ms
11,904 KB
testcase_11 AC 37 ms
11,904 KB
testcase_12 AC 36 ms
11,776 KB
testcase_13 AC 750 ms
35,608 KB
testcase_14 AC 364 ms
13,568 KB
testcase_15 AC 344 ms
17,152 KB
testcase_16 AC 1,083 ms
20,608 KB
testcase_17 AC 1,298 ms
25,600 KB
testcase_18 AC 1,118 ms
24,448 KB
testcase_19 AC 60 ms
12,032 KB
testcase_20 AC 417 ms
16,000 KB
testcase_21 AC 235 ms
12,800 KB
testcase_22 AC 697 ms
16,384 KB
testcase_23 TLE -
testcase_24 AC 727 ms
19,700 KB
testcase_25 AC 69 ms
12,160 KB
testcase_26 AC 1,440 ms
29,952 KB
testcase_27 AC 70 ms
11,904 KB
testcase_28 AC 740 ms
19,520 KB
testcase_29 AC 1,560 ms
66,572 KB
testcase_30 AC 1,837 ms
66,772 KB
testcase_31 TLE -
testcase_32 TLE -
testcase_33 -- -
testcase_34 -- -
testcase_35 -- -
testcase_36 -- -
testcase_37 -- -
testcase_38 -- -
testcase_39 -- -
testcase_40 -- -
testcase_41 -- -
testcase_42 -- -
testcase_43 -- -
testcase_44 -- -
testcase_45 -- -
testcase_46 -- -
testcase_47 -- -
testcase_48 -- -
testcase_49 -- -
testcase_50 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

# TODO
# https://www.cnblogs.com/alex-wei/p/17531487.html
# https://zhuanlan.zhihu.com/p/672216458
# 理解:体积很大的多重背包问题
#
# 有趣的是,同余最短路不应该从最短路的角度考虑。
# !其本质上是根据单调性值域定义域互换后将完全背包转化为体积模m意义下的完全背包。
# 普通完全背包的转移是有向无环图,而环上完全背包转移成环,这让我们想到最短路。
# !但因为一个点不会经过它自己,对应原问题就是对于一个物品,不会使得它的总体积为基准物品体积的倍数,
# 所以,我们可以将完全背包转化为类多重背包问题。
#
# for(int i = 0, lim = __gcd(v[i], m); i < lim; i++)
#   for(int j = i, c = 0; c < 2; c += j == i) {
#     int p = (j + v[i]) % m;
#     f[p] = min(f[p], f[j] + v[i]), j = p;
#   }


from math import gcd
from typing import Iterable, List, Tuple

INF = int(4e18)


def min2(a: int, b: int) -> int:
    return a if a < b else b


def max2(a: int, b: int) -> int:
    return a if a > b else b


def modShortestPath(coeffs: Iterable[int]) -> Tuple[int, List[int]]:
    """确定线性组合∑ai*xi的可能取到的值(ai非负)

    Args:
        coeffs (List[int]): 非负整数系数,最小的非零ai称为base

    Returns:
        Tuple[int, List[int]]: base, dist
        base (int): 最小的非零ai
        dist (List[int]): dist[i]记录的是最小的x,满足x=i(mod base)且x能被系数coeffs线性表出(xi非负)
        如果不存在这样的x,则dist[i]为INF
        如果coeff全为0,则返回空数组
    """
    coeffs = [v for v in coeffs if v > 0]
    if not coeffs:
        return 0, []

    base = min(coeffs)
    dp = [INF] * base  # dp[i]表示模base余数为i时,最小的k
    dp[0] = 0
    for v in coeffs:
        cycle = gcd(base, v)  # 在这些环上转移
        for j in range(cycle):
            cur = j
            count = 0
            while count < 2:  # 转两圈,涵盖从每个点出发的情况
                next = (cur + v) % base
                dp[next] = min2(dp[next], dp[cur] + v)
                cur = next
                count += cur == j
    return base, dp


# P2371 [国家集训队] 墨墨的等式
# https://www.luogu.com.cn/problem/P2371
# 给定n个系数coeffs和上下界lower,upper
# !对于 lower<=k<=upper 求有多少个k能够满足
# !a0*x0+a1*x1+...+an*xn=k
# n<=12 0<=ai<=5e5 1<=lower<=upper<=2^63-1
# !时间复杂度:O(n*ai)
def p2371() -> None:
    _, lower, upper = map(int, input().split())
    coeffs = list(map(int, input().split()))
    coeffs = [v for v in coeffs if v != 0]
    if not coeffs:
        print(0)
        return

    base, dp = modShortestPath(coeffs)

    res = 0
    for i in range(base):
        if upper >= dp[i]:
            res += (upper - dp[i]) // base + 1
        if lower > dp[i]:
            res -= (lower - dp[i] - 1) // base + 1
    print(res)


def yuki1782() -> None:
    _, upper = map(int, input().split())
    lower = 1
    coeffs = list(map(int, input().split()))

    coeffs = [v for v in coeffs if v != 0]
    if not coeffs:
        print(0)
        return

    base, dp = modShortestPath(coeffs)
    res = 0
    for i in range(base):
        if upper >= dp[i]:
            res += (upper - dp[i]) // base + 1
        if lower > dp[i]:
            res -= (lower - dp[i] - 1) // base + 1
    print(res)


# P2662 牛场围栏(求最大的不能被线性表出的数)
# https://www.luogu.com.cn/problem/P2662
# 给一堆系数,求最大的不能被线性表出的数。
# 如果任何数可以被表出或者这个最大值不存在,输出-1
# n<100,ai<3000
# !从起点开始有一些点无法到达(即有一整个剩余系都不能被表出)
def p2662() -> None:
    n, cut = map(int, input().split())  # 木料的种类和每根木料削去的最大值
    sticks = list(map(int, input().split()))  # 第i根木料的原始长度
    coeffs = set()
    for s in sticks:
        for c in range(min(cut, s) + 1):
            coeffs.add(s - c)

    base, dist = modShortestPath(coeffs)
    if any(v == INF for v in dist):  # 这个剩余类不能被表出
        print(-1)
        exit(0)

    print(max(dist) - base)


# P9140 [THUPC 2023 初赛] 背包 (超大完全背包)
# https://www.luogu.com.cn/problem/P9140
#
# 有n个物品,第i种物品单个体积为vi,价值为ci
# q次询问,每次给出背包的容积,你需要选择若干个物品,
# 每种物品可以选任意多个
# !在选出物品的体积的和恰好为 V 的前提下最大化选出物品的价值的和。
# 若不存在体积和恰好为 V 的方案,输出 -1
# 为了体现你解决 NP-Hard 问题的能力,V 会远大于 vi,详见数据范围部分。
# n<=50 vi<=1e5 ci<=1e5 q<=1e5
# !1e11<=V<=1e12
# O(n*max(vi)
def p9140() -> None:
    n, q = map(int, input().split())
    goods = list(tuple(map(int, input().split())) for _ in range(n))  # !vi,ci

    baseV, baseC = 1, 0  # 性价比最高的物品
    gcd_ = 0
    for v, c in goods:
        if baseV * c > v * baseC:
            baseV, baseC = v, c
        gcd_ = gcd(gcd_, v)
    dp = [-INF] * baseV
    dp[0] = 0
    for v, c in goods:
        cycle = gcd(baseV, v)
        for j in range(cycle):
            cur = j
            count = 0
            while count < 2:
                next = (cur + v) % baseV
                # !选这个物品,就要抛弃  baseC * ((cur + v) // baseV 的价值
                dp[next] = max2(dp[next], dp[cur] + c - baseC * ((cur + v) // baseV))
                cur = next
                count += cur == j

    for _ in range(q):
        cap = int(input())
        if cap % gcd_:
            print(-1)
        else:
            print(dp[cap % baseV] + cap // baseV * baseC)


if __name__ == "__main__":
    import sys

    input = lambda: sys.stdin.readline().rstrip("\r\n")

    # p2371()
    yuki1782()
    # p2662()
    # p9140()
0