Address
Algorithm 1
設 表示考慮了前 個球選出 組的方案數,轉移顯然爲:
考慮由 怎麼得到 ,只需要討論是否恰好有包含兩個球的一組從中間跨過,即:
同理我們有:
顯然可以用 NTT 優化,因此求出 的二進制拆分逐項合併即可,時間複雜度 。
Algorithm 2
設 的生成函數:
顯然有如下遞推式:
列出特徵方程:
解得:
因此 可以表示爲:
由 解得:
代回原式即爲:
因爲 的常數項爲 ,所以 ,可以忽略。
最後的答案爲:
對於求 這樣只有常數項的多項式在模 意義下的 次冪( 爲任意有理數),實際上我們有 的做法。
記該多項式爲 ,我們所求即爲:
對兩邊同時求導,
僅針對等式兩邊次數爲 的項前面的係數列式,有:
因爲 中不爲 的項只有 個且 已知,我們從小到大枚舉 ,就可以每次 得到 。
其實可以出得很大,時間複雜度 。
Code
#include <bits/stdc++.h>
template <class T>
inline void read(T &res)
{
char ch;
while (ch = getchar(), !isdigit(ch));
res = ch ^ 48;
while (ch = getchar(), isdigit(ch))
res = res * 10 + ch - 48;
}
template <class T>
inline void put(T x)
{
if (x > 9)
put(x / 10);
putchar(x % 10 + 48);
}
typedef long long ll;
const int N = 12e5 + 5;
const int mod = 998244353;
const int inv2 = (mod + 1) / 2;
const int inv3 = (mod + 1) / 3;
ll n;
int K; char s[N];
int inv[N], exp_a[N], rev[N], tw[N];
int _a[N], _b[N], a[N], b[N], c[N], d[N], ln_b[N], inv_a[N];
inline int quick_pow(int x, int k)
{
int res = 1;
while (k)
{
if (k & 1)
res = 1ll * res * x % mod;
x = 1ll * x * x % mod;
k >>= 1;
}
return res;
}
inline void add(int &x, int y)
{
x += y;
x >= mod ? x -= mod : 0;
}
inline void dec(int &x, int y)
{
x -= y;
x < 0 ? x += mod : 0;
}
inline void NTT(int *f, int fm, int opt)
{
int g = opt == 1 ? 3 : inv3;
for (int i = 0; i < fm; ++i)
if (i < rev[i])
std::swap(f[i], f[rev[i]]);
for (int k = 1; k < fm; k <<= 1)
{
int w = quick_pow(g, (mod - 1) / (k << 1));
tw[0] = 1;
for (int i = 1; i < k; ++i)
tw[i] = 1ll * tw[i - 1] * w % mod;
for (int i = 0; i < fm; i += k << 1)
for (int j = 0, *f1 = f + i, *f2 = f + i + k; j < k; ++j, ++f1, ++f2)
{
int u = *f1,
v = 1ll * tw[j] * (*f2) % mod;
*f1 = *f2 = u;
add(*f1, v);
dec(*f2, v);
}
}
if (opt == -1)
{
for (int i = 0, inv = quick_pow(fm, mod - 2); i < fm; ++i)
f[i] = 1ll * f[i] * inv % mod;
}
}
inline void poly_mul(int *a, int am, int *b, int bm)
{
int tot = am + bm, fm, k = -1;
if (tot <= 256)
{
for (int i = 0; i <= am; ++i)
for (int j = 0; j <= bm; ++j)
_b[i + j] = (1ll * a[i] * b[j] + _b[i + j]) % mod;
for (int i = 0; i <= tot; ++i)
a[i] = _b[i], _b[i] = 0;
for (int i = 0; i <= bm; ++i)
b[i] = 0;
}
else
{
for (fm = 1; fm <= tot; fm <<= 1, ++k);
for (int i = 1; i < fm; ++i)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << k);
NTT(a, fm, 1);
NTT(b, fm, 1);
for (int i = 0; i < fm; ++i)
a[i] = 1ll * a[i] * b[i] % mod;
NTT(a, fm, -1);
for (int i = 0; i < fm; ++i)
b[i] = 0;
}
}
inline void poly_inv(int *a, int am)
{
inv_a[0] = quick_pow(a[0], mod - 2);
int k = 1, cnt = 0;
while (k <= am)
{
k <<= 1, ++cnt;
int fm = k << 1;
for (int i = 1; i < fm; ++i)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << cnt);
for (int i = 0; i < k; ++i)
c[i] = a[i];
NTT(inv_a, fm, 1);
NTT(c, fm, 1);
for (int i = 0; i < fm; ++i)
{
int tmp = inv_a[i];
add(inv_a[i], tmp);
dec(inv_a[i], 1ll * c[i] * tmp % mod * tmp % mod);
}
NTT(inv_a, fm, -1);
for (int i = k; i < fm; ++i)
inv_a[i] = 0;
for (int i = 0; i < fm; ++i)
c[i] = 0;
}
for (int i = 0; i <= am; ++i)
a[i] = inv_a[i];
for (int i = 0; i < k; ++i)
inv_a[i] = 0;
}
inline void poly_der(int *a, int am)
{
for (int i = 0; i < am; ++i)
a[i] = 1ll * a[i + 1] * (i + 1) % mod;
a[am] = 0;
}
inline void poly_int(int *a, int am)
{
for (int i = am + 1; i >= 1; --i)
a[i] = 1ll * a[i - 1] * inv[i] % mod;
a[0] = 0;
}
inline void poly_ln(int *a, int am)
{
for (int i = 0; i <= am; ++i)
d[i] = a[i];
poly_der(a, am);
poly_inv(d, am);
poly_mul(a, am - 1, d, am);
for (int i = am, im = am + am - 1; i <= im; ++i)
a[i] = 0;
poly_int(a, am - 1);
}
inline void poly_exp(int *a, int am)
{
exp_a[0] = 1;
int k = 1, cnt = 0;
while (k <= am)
{
k <<= 1, ++cnt;
int fm = k << 1;
for (int i = 0; i < k; ++i)
ln_b[i] = exp_a[i];
poly_ln(ln_b, k - 1);
for (int i = 0; i < k; ++i)
{
int tmp = ln_b[i];
ln_b[i] = a[i];
dec(ln_b[i], tmp);
}
add(ln_b[0], 1);
if (fm <= 512)
{
for (int i = 0; i < fm; ++i)
_b[i] = 0;
for (int i = 0; i < k; ++i)
for (int j = 0; j < k; ++j)
_b[i + j] = (1ll * exp_a[i] * ln_b[j] + _b[i + j]) % mod;
for (int i = 0; i < fm; ++i)
exp_a[i] = _b[i], _b[i] = 0;
}
else
{
for (int i = 1; i < fm; ++i)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << cnt);
NTT(exp_a, fm, 1);
NTT(ln_b, fm, 1);
for (int i = 0; i < fm; ++i)
exp_a[i] = 1ll * exp_a[i] * ln_b[i] % mod;
NTT(exp_a, fm, -1);
}
for (int i = k; i < fm; ++i)
exp_a[i] = 0;
for (int i = 0; i < fm; ++i)
ln_b[i] = 0;
}
for (int i = 0; i <= am; ++i)
a[i] = exp_a[i];
for (int i = 0; i < k; ++i)
exp_a[i] = 0;
}
inline void poly_pow(int *a, int am, int k)
{
poly_ln(a, am);
for (int i = 0; i <= am; ++i)
a[i] = 1ll * a[i] * k % mod;
poly_exp(a, am);
}
template <class T>
inline T Max(T x, T y) {return x > y ? x : y;}
template <class T>
inline T Min(T x, T y) {return x < y ? x : y;}
inline void poly_pow_s(int *a, int am, int *b, int bm, int K)
{
b[0] = 1;
for (int i = 0; i < bm; ++i)
{
int res = 0;
for (int j = 0, jm = Min(i, am - 1); j <= jm; ++j)
res = (1ll * a[j + 1] * (j + 1) % mod * b[i - j] + res) % mod;
res = 1ll * K * res % mod;
for (int j = Max(i - 2, 0); j < i; ++j)
dec(res, 1ll * b[j + 1] * (j + 1) % mod * a[i - j] % mod);
b[i + 1] = 1ll * res * inv[i + 1] % mod;
}
}
int main()
{
read(n); read(K);
inv[1] = 1;
for (int i = 2; i <= K; ++i)
inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
_a[0] = 1, _a[1] = 6, _a[2] = 1;
poly_pow_s(_a, 2, a, K, inv2);
poly_pow_s(_a, 2, b, K, mod - inv2);
add(a[0], 1);
add(a[1], 1);
for (int i = 0; i <= K; ++i)
a[i] = 1ll * a[i] * inv2 % mod;
poly_pow(a, K, (n + 1) % mod);
poly_mul(a, K, b, K);
for (int i = 1; i <= K; ++i)
put(i <= n ? a[i] : 0), putchar(' ');
fclose(stdin); fclose(stdout);
return 0;
}