結果

問題 No.3169 [Cherry 7th Tune] Desire for Approval
ユーザー ゼット
提出日時 2025-05-30 23:53:03
言語 PyPy3
(7.3.15)
結果
TLE  
実行時間 -
コード長 11,166 bytes
コンパイル時間 695 ms
コンパイル使用メモリ 81,548 KB
実行使用メモリ 159,796 KB
最終ジャッジ日時 2025-05-30 23:53:32
合計ジャッジ時間 13,490 ms
ジャッジサーバーID
(参考情報)
judge4 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 15 TLE * 1 -- * 30
権限があれば一括ダウンロードができます

ソースコード

diff #

from __future__ import annotations
input


class CombLUT:
   MOD = 998_244_353

   _max = 0

   F = [1]
   InvF = [1]
   _fibo = [0, 1]
   _lucas = [2, 1]

   @classmethod
   def expand(cls, n):
      if n <= cls._max: return
      n = n*4//3
      cls.F.extend([1]*(n - cls._max))
      for i in range(cls._max + 1, n+1):
         cls.F[i] = cls.F[i-1] * i % cls.MOD
      cls.InvF.extend([1]*(n - cls._max))
      cls.InvF[n] = pow(cls.F[n], -1, cls.MOD)
      for i in range(n-1, cls._max, -1):
         cls.InvF[i] = cls.InvF[i+1] * (i+1) % cls.MOD
      cls._max = n

   @classmethod
   def comb(cls, n, r):
      if not (0 <= r <= n):
         return 0
      if n > cls._max: cls.expand(n)
      return cls.F[n] * cls.InvF[r] % cls.MOD * cls.InvF[n-r] % cls.MOD

   @classmethod
   def hyper_comb(cls, n, r):
      if (r < 0): return 0
      if (n < 0): return 0
      if n == r == 0: return 1
      if not (0 <= r <= n-1+r):
         return 0
      return cls.comb(n-1+r, r)

   @classmethod
   def neg_hyper_comb(cls, n, r):
      if (r < 0): return 0
      if n >= 0: return cls.hyper_comb(n, r)
      sgn = -1 if r&1 else 1
      return sgn * cls.comb(-n, r)

   @classmethod
   def factorial(cls, n):
      assert 0 <= n
      if n > cls._max: cls.expand(n)
      return cls.F[n]

   @classmethod
   def inv_factorial(cls, n):
      assert 0 <= n
      if n > cls._max: cls.expand(n)
      return cls.InvF[n]


def subset_sum(A, *, func=None, initial=None):
   if (func is None):
      if initial is None: initial = 0
      N = len(A)
      dp = [initial] * (1<<N)
      for h in range(N):
         for S in range(1<<h):
            dp[S|(1<<h)] = dp[S] + A[h]
      return dp
   else:
      assert (initial is not None)
      N = len(A)
      dp = [initial] * (1<<N)
      for h in range(N):
         for S in range(1<<h):
            dp[S|(1<<h)] = func(dp[S], A[h])
      return dp


class Convolution:
   """
    A class to perform convolution using the Fast Fourier Transform (FFT) algorithm.

    Attributes:
        _mod (int): A prime modulus used for modular arithmetic. Defaults to 998244353.
        _rank2 (int): The highest power of 2 dividing (mod - 1).
        _root (int): A primitive root of the modulus.
        _imag (int): Imaginary unit under the modulus.
        _iimag (int): Inverse of the imaginary unit under the modulus.
        _rate2 (tuple[int]): Precomputed powers of the primitive root, used for the FFT.
        _irate2 (tuple[int]): Precomputed inverse powers of the primitive root.
        _rate3 (tuple[int]): Precomputed powers of the primitive root for 3rd roots of unity.
        _irate3 (tuple[int]): Precomputed inverse powers for 3rd roots of unity.

    Note:
        This class uses a fixed modulus (998244353) by default. The modulus can be changed
        using the set_mod method, but be aware that changing the modulus can result in a
        significant performance drop on pypy. This is because, for the default modulus,
        division operations are optimized as constant divisions on pypy, but for custom
        moduli, these optimizations are not applied.
    """
   _mod = 998244353
   _rank2 = 23
   _root = 3
   _imag = 911660635
   _iimag = 86583718
   _rate2 = (
      911660635, 509520358, 369330050, 332049552, 983190778, 123842337, 238493703, 975955924, 603855026, 856644456,
      131300601, 842657263, 730768835, 942482514, 806263778, 151565301, 510815449, 503497456, 743006876, 741047443,
      56250497, 867605899
   )
   _irate2 = (
      86583718, 372528824, 373294451, 645684063, 112220581, 692852209, 155456985, 797128860, 90816748, 860285882,
      927414960, 354738543, 109331171, 293255632, 535113200, 308540755, 121186627, 608385704, 438932459, 359477183,
      824071951, 103369235
   )
   _rate3 = (
      372528824, 337190230, 454590761, 816400692, 578227951, 180142363, 83780245, 6597683, 70046822, 623238099,
      183021267, 402682409, 631680428, 344509872, 689220186, 365017329, 774342554, 729444058, 102986190, 128751033,
      395565204
   )
   _irate3 = (
      509520358, 929031873, 170256584, 839780419, 282974284, 395914482, 444904435, 72135471, 638914820, 66769500,
      771127074, 985925487, 262319669, 262341272, 625870173, 768022760, 859816005, 914661783, 430819711, 272774365,
      530924681
   )

   @classmethod
   def set_mod(cls, mod: int) -> None:
      """
        Sets a new modulus and recalculates the associated parameters.

        Args:
            mod (int): The new prime modulus.
        """
      cls._mod = mod
      cls._root = PrimeFactor.primitive_root(mod)
      cls._rank2 = tzcount(mod-1)
      root = [0]*(cls._rank2 + 1)
      iroot = [0]*(cls._rank2 + 1)
      root[cls._rank2] = pow(cls._root, (mod-1)>>cls._rank2, mod)
      iroot[cls._rank2] = pow(root[cls._rank2], mod-2, mod)
      for i in range(cls._rank2 - 1, -1, -1):
         root[i] = root[i+1] * root[i+1] % mod
         iroot[i] = iroot[i+1] * iroot[i+1] % mod
      cls._imag = root[2]
      cls._iimag = iroot[2]
      cls._rate2, cls._irate2 = cls.__calculate_rates(root, iroot, 2)
      cls._rate3, cls._irate3 = cls.__calculate_rates(root, iroot, 3)

   @classmethod
   def __calculate_rates(cls, root: list, iroot: list, ofs: int) -> tuple:
      """
        Calculates the rates used in the butterfly transformations.

        Args:
            root (list): List of roots.
            iroot (list): List of inverse roots.
            ofs (int): Offset to start calculation.

        Returns:
            tuple: A tuple containing two lists: rates and inverse rates.
        """
      rate = [0]*max(0, cls._rank2 - (ofs-1))
      irate = [0]*max(0, cls._rank2 - (ofs-1))
      prod, iprod = 1, 1
      for i in range(cls._rank2 - (ofs-1)):
         rate[i] = root[i + ofs] * prod % cls._mod
         irate[i] = iroot[i + ofs] * iprod % cls._mod
         prod *= iroot[i + ofs]
         prod %= cls._mod
         iprod *= root[i + ofs]
         iprod %= cls._mod
      return rate, irate

   @classmethod
   def butterfly(cls, a: list[int]) -> None:
      """
        Applies the butterfly transformation on the input list.

        Args:
            a (list[int]): The input list.
        """
      n = len(a)
      h = (n-1).bit_length()
      for len_ in range(0, h-1, 2):
         p = 1<<(h - len_ - 2)
         rot = 1
         for s in range(1<<len_):
            rot2 = rot*rot%cls._mod
            rot3 = rot2*rot%cls._mod
            offset = s<<(h - len_)
            for i in range(p):
               a0 = a[i + offset]
               a1 = a[i + offset + p] * rot % cls._mod
               a2 = a[i + offset + p*2] * rot2 % cls._mod
               a3 = a[i + offset + p*3] * rot3 % cls._mod
               a1na3imag = (a1-a3) * cls._imag % cls._mod
               a[i + offset] = (a0+a2+a1+a3) % cls._mod
               a[i + offset + p] = (a0+a2-a1-a3) % cls._mod
               a[i + offset + p*2] = (a0-a2 + a1na3imag) % cls._mod
               a[i + offset + p*3] = (a0-a2 - a1na3imag) % cls._mod
            if s+1 != 1<<len_:
               rot *= cls._rate3[(~s& -~s).bit_length() - 1]
               rot %= cls._mod
      if h&1:
         rot = 1
         for s in range(1<<(h-1)):
            offset = s<<1
            l = a[offset]
            r = a[offset + 1] * rot % cls._mod
            a[offset] = (l+r) % cls._mod
            a[offset + 1] = (l-r) % cls._mod
            if s+1 != 1<<(h-1):
               rot *= cls._rate2[(~s& -~s).bit_length() - 1]
               rot %= cls._mod

   @classmethod
   def butterfly_inv(cls, a: list[int]) -> None:
      """
        Applies the inverse butterfly transformation on the input list.

        Args:
            a (list[int]): The input list.
        """
      n = len(a)
      h = (n-1).bit_length()

      for len_ in range(h, 1, -2):
         p = 1<<(h - len_)
         irot = 1
         for s in range(1<<(len_-2)):
            irot2 = irot*irot%cls._mod
            irot3 = irot2*irot%cls._mod
            offset = s<<(h - len_ + 2)
            for i in range(p):
               a0 = a[i + offset]
               a1 = a[i + offset + p]
               a2 = a[i + offset + p*2]
               a3 = a[i + offset + p*3]
               a2na3iimag = (a2-a3) * cls._iimag % cls._mod
               a[i + offset] = (a0+a1+a2+a3) % cls._mod
               a[i + offset + p] = (a0-a1 + a2na3iimag) * irot % cls._mod
               a[i + offset + p*2] = (a0+a1-a2-a3) * irot2 % cls._mod
               a[i + offset + p*3] = (a0-a1 - a2na3iimag) * irot3 % cls._mod
            if s+1 != (1<<(len_-2)):
               irot *= cls._irate3[(~s& -~s).bit_length() - 1]
               irot %= cls._mod
      if h&1:
         p = 1<<(h-1)
         for i in range(p):
            l = a[i]
            r = a[i+p]
            a[i] = (l+r) % cls._mod
            a[i+p] = (l-r) % cls._mod

   @classmethod
   def convolution(cls, a: list[int], b: list[int]) -> list[int]:
      """
        Computes the convolution of two lists.

        Args:
            a (list[int]): First input list.
            b (list[int]): Second input list.

        Returns:
            list[int]: The convolution of a and b.

        Raises:
            ValueError: If the length of the result exceeds the supported length.
        """
      n, m = len(a), len(b)
      if n+m-1 > (1<<cls._rank2):
         raise ValueError('rank2 of given mod is too small.')
      if not n or not m: return []
      z = 1<<(n+m-2).bit_length()
      a = a + [0] * (z-n)
      b = b + [0] * (z-m)
      cls.butterfly(a)
      cls.butterfly(b)
      for i in range(z):
         a[i] *= b[i]
         a[i] %= cls._mod
      cls.butterfly_inv(a)
      a = a[:n+m-1]
      iz = pow(z, -1, cls._mod)
      for i in range(n+m-1):
         a[i] *= iz
         a[i] %= cls._mod
      return a
N=int(input())
L=[]
for i in range(N):
  k,a=map(int,input().split())
  L.append((k,a))
h=[[] for i in range(2**N)]
h[0]=[1]
v=[0]*(2**N)
s=[0]*(2**N)
mod=998244353
u=[1]*1000000
for i in range(1,100000+1):
  u[i]=u[i-1]*i
  u[i]%=mod
result=[0]*(N+1)
Z=Convolution()
r=[[] for i in range(N)]
for i in range(N):
      k,a=L[i][:]
      l=[0]*k
      for y in range(k):
        p=pow(a,y,mod)
        p*=u[y]
        p%=mod
        p=pow(p,-1,mod)
        l[y]=p
      r[i]=l[:]
for bit in range(1,2**N):
  for d in range(N):
    if (bit>>d)&1:
      s[bit]+=1
  g=[1]
  z=0
  for d in range(N):
    if (bit>>d)&1:
      k,a=L[d][:]
      z+=pow(a,-1,mod)
      z%=mod
  for d in range(N):
    if (bit>>d)&1:
      l=r[d][:]
      g=Z.convolution(h[bit-2**d],l)
      break
  v[bit]=z
  h[bit]=g
p=[1]
f=[0]*2**N
for bit in range(1,2**N):
  e=h[bit]
  score=0
  z=v[bit]
  for y in range(len(e)):
    w=e[y]*u[y]
    w%=mod
    w*=pow(z,-(y+1),mod)
    w%=mod
    score+=w
    score%=mod
  f[bit]=score
for bit in range(1,2**N):
  c=1
  for k in range(N):
    if (bit>>k)&1:
      c+=0
    else:
      c+=1
  q=0
  b=2**N-1-bit
  p=b
  while b>=0:
    score=f[bit+b]
    if s[b]%2==0:
      q+=score
    else:
      q-=score
    b-=1
    if b<0:
      break
    b&=p
  for x in range(c,N+1):
    result[x]+=q
    result[x]%=mod
result=result[1:]
print(*result)
0