G - Random Walk Distance Editorial by toam


\(M=\max N+X\) とする.

\(B\)\(\sqrt{M}\) 程度の整数としておき,各 \(k=0,1,\ldots,B\) および \(j=0,,\ldots,k\) に対して,\(\displaystyle \sum_{i=0}^{jB}\dbinom{kB}{i}\)\(O(M^{1,5})\) で求めておくことで,制約内の任意の二項係数 prefix sum を \(O(\sqrt{M})\) でオンラインで求めることができる.

mod = 998244353
B = int(410000**0.5)
N = B * B + 10

fac = [1] * N
ninv = [1] * N
finv = [1] * N

for i in range(2, N):
    fac[i] = fac[i - 1] * i % mod
    ninv[i] = (-(mod // i) * ninv[mod % i]) % mod
    finv[i] = finv[i - 1] * ninv[i] % mod


def binom(n, k):
    if n < 0 or k < 0:
        return 0
    if k > n:
        return 0
    return fac[n] * finv[k] % mod * finv[n - k] % mod


memo = []
for bi in range(B + 1):
    n = B * bi
    a = [0] * (bi + 1)
    res = 0
    q = 0
    for j in range(n + 1):
        res += binom(n, j)
        res %= mod
        if j % B == 0:
            a[q] = res
            q += 1
    memo.append(a)


inv2 = pow(2, mod - 2, mod)


def calc(n, m):
    if m < 0:
        return 0
    if m >= n:
        return pow(2, n, mod)
    n0 = ((n + B - 1) // B) * B
    bi = n0 // B
    q = m // B
    res = memo[bi][q]
    for j in range(q * B + 1, m + 1):
        res += binom(n0, j)
        res %= mod
    while n0 > n:
        res = inv2 * (res + binom(n0 - 1, m)) % mod
        n0 -= 1
    return res


def f(n, l, r):
    if l > r:
        return 0
    return (calc(n, r) - calc(n, l - 1)) % mod


for _ in range(int(input())):
    n, x = map(int, input().split())
    print(((2 * (n + x) * f(n, 0, (n + x) // 2) - 4 * n * f(n - 1, 0, (n + x) // 2 - 1)) % mod * pow(inv2, n, mod) - x) % mod)

posted:
last update: