Description:
题解:
不难发现当r=1时就是选若干上升序列。
而一列至少有一行不满足就不稳定的。
这个破限制肯定要想方设法用容斥搞掉。
至少一行不满足太难算了,不妨改成算全部都满足,假设有i个列需要不稳定,即0列全部满足,但是有j个列全部满足,即稳定,则容斥系数为 ( − 1 ) j (-1)^{j} (−1)j
这样就可以得到一个显然的dp,先把整个序列每k个分块,最后一块不完整先不管。
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示前i块,选了j个上升序列,ps.那么有i-j个全部满足的列
注意用EGF去搞上升序列的选择。
f
[
i
]
[
j
]
=
∑
u
=
0
i
−
1
f
[
u
]
[
j
−
1
]
∗
(
1
/
(
(
i
−
u
)
k
)
!
)
r
f[i][j]=\sum_{u=0}^{i-1}f[u][j-1]*{(1/((i-u)k)!)^r}
f[i][j]=∑u=0i−1f[u][j−1]∗(1/((i−u)k)!)r
A
n
s
=
n
!
∗
∑
i
=
0
m
∑
j
=
0
m
f
[
i
]
[
j
]
∗
(
(
n
−
i
k
)
!
)
r
∗
(
−
1
)
m
−
j
∗
(
−
1
)
m
Ans=n!*\sum_{i=0}^m \sum_{j=0}^m f[i][j]*((n-ik)!)^r*(-1)^{m-j}*(-1)^m
Ans=n!∗∑i=0m∑j=0mf[i][j]∗((n−ik)!)r∗(−1)m−j∗(−1)m
这里
m
=
(
n
−
1
)
/
k
m=(n-1)/k
m=(n−1)/k
发现j这一维其实没有用,因为转移时每次j就是+1,那么对最终统计的贡献就是*-1
f
[
i
]
=
−
∑
u
=
0
i
−
1
f
[
u
]
∗
(
1
/
(
(
i
−
u
)
k
)
!
)
r
f[i]=-\sum_{u=0}^{i-1}f[u]*{(1/((i-u)k)!)^r}
f[i]=−∑u=0i−1f[u]∗(1/((i−u)k)!)r
A
n
s
=
n
!
∗
∑
i
=
0
m
f
[
i
]
∗
(
(
n
−
i
k
)
!
)
r
∗
(
−
1
)
i
∗
(
−
1
)
m
−
i
Ans=n!*\sum_{i=0}^mf[i]*((n-ik)!)^r*(-1)^i*(-1)^{m-i}
Ans=n!∗∑i=0mf[i]∗((n−ik)!)r∗(−1)i∗(−1)m−i
A
n
s
=
n
!
∗
∑
i
=
0
m
f
[
i
]
∗
(
(
n
−
i
k
)
!
)
r
∗
(
−
1
)
m
Ans=n!*\sum_{i=0}^mf[i]*((n-ik)!)^r*(-1)^m
Ans=n!∗∑i=0mf[i]∗((n−ik)!)r∗(−1)m
观察f的转移:
f
[
i
]
=
−
∑
u
=
0
i
−
1
f
[
u
]
∗
(
1
/
(
(
i
−
u
)
k
)
!
)
r
f[i]=-\sum_{u=0}^{i-1}f[u]*{(1/((i-u)k)!)^r}
f[i]=−∑u=0i−1f[u]∗(1/((i−u)k)!)r
不难得到分治NTT的做法,但是显然这可以求逆:
设
G
[
i
>
0
]
=
(
1
/
(
i
k
)
!
)
r
G[i>0]=(1/(ik)!)^r
G[i>0]=(1/(ik)!)r,则
F
=
G
∗
F
+
1
F=G*F+1
F=G∗F+1
F
=
1
/
(
1
−
G
)
F=1/(1-G)
F=1/(1−G)
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define pp printf
#define ll long long
using namespace std;
const int mo = 998244353;
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
const int N = 2097152;
ll a[N]; int r[N];
void dft(ll *a, int n, int F) {
ff(i, 0, n) {
r[i] = r[i / 2] / 2 + (i & 1) * n / 2;
if(i < r[i]) swap(a[i], a[r[i]]);
}
for(int h = 1; h < n; h *= 2) {
ll wn = ksm(ksm(3, (mo - 1) / 2 / h), F == 1 ? 1 : mo - 2);
for(int j = 0; j < n; j += 2 * h) {
ll A, *l = a + j, *r = a + j + h, w = 1;
ff(i, 0, h) {
A = *r * w, *r = (*l - A) % mo, *l = (*l + A) % mo;
w = w * wn % mo, l ++, r ++;
}
}
}
if(F == -1) {
ll v = ksm(n, mo - 2);
ff(i, 0, n) a[i] = (a[i] + mo) * v % mo;
}
}
typedef vector<ll> V;
#define si size()
void dft(V &p, int F) {
ff(i, 0, p.si) a[i] = p[i];
dft(a, p.si, F);
ff(i, 0, p.si) p[i] = a[i];
}
V qni(V a) {
int n0 = 1; while(n0 <= a.si) n0 *= 2;
V b; b.resize(1); b[0] = ksm(a[0], mo - 2);
for(int n = 2; n <= n0; n *= 2) {
V c = a, d = b; c.resize(n);
c.resize(2 * n); dft(c, 1);
b.resize(2 * n); dft(b, 1);
ff(i, 0, 2 * n) b[i] = b[i] * b[i] % mo * c[i] % mo;
dft(b, -1); b.resize(n); d.resize(n);
ff(i, 0, n) b[i] = (2 * d[i] - b[i] + mo) % mo;
}
b.resize(a.si); return b;
}
int n, R, k, m;
ll fac[N], ans;
vector<ll> g;
int main() {
freopen("interstellar.in", "r", stdin);
freopen("interstellar.out", "w", stdout);
scanf("%d %d %d", &n, &R, &k);
fac[0] = 1; fo(i, 1, n) fac[i] = fac[i - 1] * i % mo;
ll fn = fac[n];
fo(i, 0, n) fac[i] = ksm(fac[i], mo - 2);
m = (n - 1) / k;
g.resize(m + 1);
fo(i, 0, m) g[i] = ksm(fac[i * k], R);
g[0] = 1; g = qni(g);
fo(i, 0, m) ans += g[i] * ksm(fac[n - i * k], R) % mo;
ans = (ans % mo * ((m & 1) ? -1 : 1) + mo) * ksm(fn, R) % mo;
pp("%lld\n", ans);
}