結果
| 問題 |
No.1068 #いろいろな色 / Red and Blue and more various colors (Hard)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2021-07-11 21:11:48 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 2,895 ms / 3,500 ms |
| コード長 | 2,850 bytes |
| コンパイル時間 | 173 ms |
| コンパイル使用メモリ | 82,176 KB |
| 実行使用メモリ | 265,272 KB |
| 最終ジャッジ日時 | 2024-07-02 03:15:57 |
| 合計ジャッジ時間 | 56,766 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 29 |
ソースコード
import sys
input = lambda : sys.stdin.readline().rstrip()
sys.setrecursionlimit(2*10**5+10)
write = lambda x: sys.stdout.write(x+"\n")
debug = lambda x: sys.stderr.write(x+"\n")
writef = lambda x: print("{:.12f}".format(x))
n,q = list(map(int, input().split()))
a = list(map(int, input().split()))
b = list(map(int, input().split()))
M = 998244353
a = [v%M for v in a]
# NTT
def factor(n, m=None):
# mを与えると、高々その素因数まで見て、残りは分解せずにそのまま出力する
f = {}
tmp = n
M = int(-(-n**0.5//1))+1
if m is not None:
M = min(m+1, M)
for i in range(2, M+1):
if tmp<i:
break
if tmp%i==0:
cnt=0
while tmp%i==0:
cnt+=1
tmp //= i
f[i] = cnt
if tmp!=1:
f[tmp] = 1
if not f:
f[n] = 1
return f
def primitive_root(p):
if p == 2:
return 1
if p == 167772161:
return 3
if p == 469762049:
return 3
if p == 754974721:
return 11
if p == 998244353:
return 3
g = 2
f = factor(p-1)
while True:
if all(pow(g,(p-1)//k,p)!=1 for k in f.keys()):
break
g += 1
return g
# 順番は変わる
def ntt(A,n):
for i in range(n):
m = 1 << (n-i-1)
for start in range(1 << i):
w = 1
start *= m*2
for j in range(m):
A[start+j],A[start+j+m] = (A[start+j]+A[start+j+m]) % M,(A[start+j]-A[start+j+m])*w % M
w *= roots[n-i]
w %= M
return A
def inv_ntt(A,n):
for i in range(n):
m = 1 << i
for start in range(1 << (n-i-1)):
w = 1
start *= m*2
for j in range(m):
A[start+j],A[start+j+m] = (A[start+j]+A[start+j+m]*w) % M,(A[start+j]-A[start+j+m]*w) % M
w *= inv_roots[i+1]
w %= M
a = pow(2,n*(M-2),M)
for i in range(1 << n):
A[i] *= a
A[i] %= M
return A
def conv(A,B):
a,b = len(A),len(B)
deg = a+b-2
n = deg.bit_length()
N = 1 << n
A += [0]*(N-a) # A の次数を 2冪-1 にする
B += [0]*(N-b) # B の次数を 2冪-1 にする
A = ntt(A,n)
B = ntt(B,n)
C = [(A[i]*B[i]) % M for i in range(N)]
C = inv_ntt(C,n)
return C[:deg+1]
pr = primitive_root(M)
roots = [pow(pr,(M-1) >> i,M) for i in range(24)]
inv_roots = [pow(r,M-2,M) for r in roots]
# roots[i] = 1 の 2**i 乗根、inv_roots[i] = 1 の 2**i 乗根の逆元
h = [[v-1,1] for v in a]
while len(h)>=2:
nh = []
if len(h)%2==0:
pass
else:
nh.append(h.pop())
for i in range(0, len(h), 2):
nh.append(conv(h[i], h[i+1]))
h = nh
c = h[0]
ans = [c[i]%M for i in b]
write("\n".join(map(str, ans)))