結果
| 問題 | No.3414 Aperiodic Sequence |
| コンテスト | |
| ユーザー |
wolgnik
|
| 提出日時 | 2025-12-18 14:31:36 |
| 言語 | Kotlin (2.1.0) |
| 結果 |
AC
|
| 実行時間 | 2,136 ms / 3,000 ms |
| コード長 | 6,745 bytes |
| 記録 | |
| コンパイル時間 | 19,516 ms |
| コンパイル使用メモリ | 519,676 KB |
| 実行使用メモリ | 122,148 KB |
| 最終ジャッジ日時 | 2025-12-20 23:31:59 |
| 合計ジャッジ時間 | 39,383 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 15 |
ソースコード
import java.io.PrintWriter
const val MOD = 998244353L
fun main() {
val br = System.`in`.bufferedReader()
val bw = PrintWriter(System.out)
val (n, m) = br.readLine().split(" ").map { it.toInt() }
val v = if (n > 0) br.readLine().split(" ").map { it.toLong() } else emptyList()
val conv = Convolution()
// g[k] = sum of v[i]^k の計算
val g = calcG(v, m, conv)
// メビウス関数
val mobius = IntArray(m + 1)
mobius[1] = 1
val spf = IntArray(m + 1) { it } // smallest prime factor
for (i in 2..Math.sqrt(m.toDouble()).toInt()) {
if (spf[i] == i) {
var j = i * i
while (j <= m) {
if (spf[j] == j) spf[j] = i
j += i
}
}
}
for (i in 2..m) {
val p = spf[i]
val prev = i / p
mobius[i] = if (prev % p == 0) 0 else -mobius[prev]
}
// 約数列挙
val divisors = Array(m + 1) { mutableListOf<Int>() }
for (i in 1..m) {
var j = i
while (j <= m) {
divisors[j].add(i)
j += i
}
}
// solve
val res = StringBuilder()
for (n in 1..m) {
var f = 0L
for (d in divisors[n]) {
val mu = mobius[n / d]
if (mu != 0) {
val base = g[n / d]
val pw = powMod(base, d.toLong())
f = (f + mu * pw % MOD + MOD) % MOD
}
}
if (n > 1) res.append(' ')
res.append(f)
}
bw.println(res)
bw.flush()
}
fun powMod(a: Long, b: Long): Long {
var result = 1L
var base = (a % MOD + MOD) % MOD
var exp = b
while (exp > 0) {
if (exp and 1L == 1L) result = result * base % MOD
base = base * base % MOD
exp = exp shr 1
}
return result
}
fun modInverse(a: Long): Long = powMod(a, MOD - 2)
class Convolution {
private val W = LongArray(24) { powMod(3L, (MOD - 1) shr it) }
private val iW = LongArray(24) { powMod(332748118L, (MOD - 1) shr it) }
private fun fmt(k: Int, a: LongArray) {
for (l in k downTo 1) {
val d = 1 shl (l - 1)
val w = W[l]
var i = 0
while (i < a.size) {
var u = 1L
for (j in 0 until d) {
val s = i + j
val as_ = a[s]
val asd = a[s + d]
a[s] = (as_ + asd) % MOD
a[s + d] = u * ((as_ - asd) % MOD + MOD) % MOD
u = u * w % MOD
}
i += d * 2
}
}
}
private fun ifmt(k: Int, a: LongArray) {
for (l in 1..k) {
val d = 1 shl (l - 1)
val w = iW[l]
var i = 0
while (i < a.size) {
var u = 1L
for (j in 0 until d) {
val s = i + j
val tmp = a[s + d] * u % MOD
a[s + d] = ((a[s] - tmp) % MOD + MOD) % MOD
a[s] = (a[s] + tmp) % MOD
u = u * w % MOD
}
i += d * 2
}
}
}
fun convolve(a: List<Long>, b: List<Long>): LongArray {
val n0 = a.size + b.size - 1
if (n0 == 1) {
return longArrayOf(a[0] * b[0] % MOD)
}
// 小さい場合は愚直計算
if (minOf(a.size, b.size) <= 50) {
val res = LongArray(n0)
for (i in a.indices) {
for (j in b.indices) {
res[i + j] = (res[i + j] + a[i] * b[j]) % MOD
}
}
return res
}
val k = Integer.SIZE - Integer.numberOfLeadingZeros(n0 - 1).coerceAtLeast(0)
val n = 1 shl k
val A = LongArray(n)
val B = LongArray(n)
for (i in a.indices) A[i] = a[i]
for (i in b.indices) B[i] = b[i]
fmt(k, A)
fmt(k, B)
for (i in 0 until n) {
A[i] = A[i] * B[i] % MOD
}
ifmt(k, A)
val invn = modInverse(n.toLong())
val res = LongArray(n0)
for (i in 0 until n0) {
res[i] = A[i] * invn % MOD
}
return res
}
}
fun fpsInv(f: List<Long>, deg: Int, conv: Convolution): LongArray {
var res = longArrayOf(modInverse(f[0]))
var d = 1
while (d < deg) {
d = d shl 1
val fTrunc = f.subList(0, minOf(f.size, d))
var fg = conv.convolve(res.toList(), fTrunc)
// fg = -fg
for (i in fg.indices) {
fg[i] = (MOD - fg[i]) % MOD
}
// 必要なら拡張
if (fg.size < d) {
val newFg = LongArray(d)
fg.copyInto(newFg)
fg = newFg
}
fg[0] = (fg[0] + 2) % MOD
res = conv.convolve(res.toList(), fg.toList())
if (res.size > d) {
res = res.copyOf(d)
}
}
return if (res.size > deg) res.copyOf(deg) else res
}
fun calcG(v: List<Long>, m: Int, conv: Convolution): LongArray {
val n = v.size
if (n == 0) {
return LongArray(m + 1)
}
val deg = m + 2
// polys = [[1, -vi % mod] for vi in v]
var polys = v.map { vi -> listOf(1L, (MOD - vi % MOD) % MOD) }.toMutableList()
// 分割統治で多項式を掛け合わせる
while (polys.size > 1) {
val newPolys = mutableListOf<List<Long>>()
var i = 0
while (i < polys.size) {
if (i + 1 < polys.size) {
var qNew = conv.convolve(polys[i], polys[i + 1])
if (qNew.size > deg) {
qNew = qNew.copyOf(deg)
}
newPolys.add(qNew.toList())
} else {
newPolys.add(polys[i])
}
i += 2
}
polys = newPolys
}
val Q = if (polys[0].size > deg) polys[0].subList(0, deg) else polys[0]
// Q_deriv = [(k+1) * Q[k+1] for k in range(len(Q)-1)]
val qDeriv = LongArray(Q.size - 1) { k -> ((k + 1).toLong() * Q[k + 1]) % MOD }
// neg_Q_deriv = -Q_deriv
val negQDeriv = LongArray(qDeriv.size) { (MOD - qDeriv[it]) % MOD }
val qInv = fpsInv(Q, m + 1, conv)
var s = conv.convolve(negQDeriv.toList(), qInv.toList())
if (s.size > m + 1) {
s = s.copyOf(m + 1)
}
// return [n] + S[:M]
val result = LongArray(m + 1)
result[0] = n.toLong()
for (i in 0 until minOf(m, s.size)) {
result[i + 1] = s[i]
}
return result
}
wolgnik