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:
