結果

問題 No.3398 Accuracy of Integer Division Approximate Function 2
コンテスト
ユーザー 👑 Mizar
提出日時 2025-11-19 03:23:39
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 145 ms / 2,000 ms
コード長 1,826 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 180 ms
コンパイル使用メモリ 82,084 KB
実行使用メモリ 77,016 KB
最終ジャッジ日時 2025-12-04 23:33:07
合計ジャッジ時間 2,741 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 20
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

# -*- coding: utf-8 -*-
"""
solution for Accuracy of Integer Division Approximate Function 2
"""
import math


def mwf_leq(t: int, l: int, r: int, m: int, a: int, b: int, c: int, d: int) -> bool:
    """(max_{l <= x < r} a*x + b*floor((c*x + d)/m)) <= t"""
    assert l < r and 0 < m
    n = r - l
    qd0, d = divmod(c * l + d, m)
    sum_acc = a * l + b * qd0 - t
    if sum_acc > 0:
        return False
    while True:
        qc, c = divmod(c, m)
        a += b * qc
        qd, d = divmod(d, m)
        sum_acc += b * qd
        if sum_acc > 0:
            return False
        y_max = (c * (n - 1) + d) // m
        if (sum_acc + a * (n - 1) + b * y_max) > 0:
            return False
        if y_max == 0 or (a >= 0 and b >= 0) or (a <= 0 and b <= 0):
            return True
        if a < 0:
            sum_acc += a + b
        n, m, a, b, c, d = y_max, c, b, a, m, (m - d - 1)


def compute_xmin(d: int, a: int, b: int, k: int) -> int:
    """
    Compute xmin(D,A,B,K), return -1 if not exists
    xmin(D,A,B,K) = min{ x >= 0 | K < Δ(D,A,B,x) }
    Δ(D,A,B,x) = floor(x/D) - floor( floor(x/A) * floor(AB/D) / B )
    """
    assert d > 0 and a > 0 and b > 0 and k >= 0
    gcd_da = math.gcd(d, a)
    d_red, a_red, t_delta = d // gcd_da, a // gcd_da, b * k
    m_red, r_red = divmod(a_red * b, d_red)
    if r_red == 0 and d_red * k + 1 >= a_red:
        return -1
    lo, hi = 0, a_red * b * k + 2
    while lo + 1 < hi:
        mid = (lo + hi) // 2
        if mwf_leq(t_delta, lo, mid, a_red, b, -m_red, d_red, 0):
            lo = mid
        else:
            hi = mid
    return d * lo


if __name__ == '__main__':
    import sys
    T = int(sys.stdin.readline())
    for _ in range(T):
        D, A, B, K = map(int, sys.stdin.readline().split())
        ans = compute_xmin(D, A, B, K)
        print(ans)
0