Description
Solution
设
f
i
f_i
fi表示前
i
K
iK
iK列的答案,考虑容斥,枚举有多少段连续上升的段,则有:
f
i
=
∑
j
=
0
i
−
1
(
i
K
j
K
)
r
(
−
1
)
i
−
j
−
1
f
j
f_i=\sum_{j=0}^{i-1}\binom{iK}{jK}^r(-1)^{i-j-1}f_j
fi=j=0∑i−1(jKiK)r(−1)i−j−1fj
拆开组合数,移项得:
f
i
(
(
i
K
)
!
)
r
=
∑
j
=
0
i
−
1
f
j
(
(
j
K
)
!
)
r
⋅
(
−
1
)
i
−
j
−
1
(
(
(
i
−
j
)
k
)
!
)
r
\dfrac{f_i}{((iK)!)^r}=\sum_{j=0}^{i-1}\dfrac{f_j}{((jK)!)^r}\cdot\dfrac{(-1)^{i-j-1}}{(((i-j)k)!)^r}
((iK)!)rfi=j=0∑i−1((jK)!)rfj⋅(((i−j)k)!)r(−1)i−j−1
设
F
(
x
)
=
∑
i
=
0
∞
f
i
(
(
i
K
)
!
)
r
,
G
(
x
)
=
∑
i
=
1
∞
(
−
1
)
i
−
1
(
(
i
K
)
!
)
r
F(x)=\sum_{i=0}^{\infin}\dfrac{f_i}{((iK)!)^r},G(x)=\sum_{i=1}^{\infin}\dfrac{(-1)^{i-1}}{((iK)!)^r}
F(x)=∑i=0∞((iK)!)rfi,G(x)=∑i=1∞((iK)!)r(−1)i−1
则
F
(
x
)
=
F
(
x
)
G
(
x
)
+
1
F(x)=F(x)G(x)+1
F(x)=F(x)G(x)+1,即
F
(
x
)
=
1
1
−
G
(
x
)
F(x)=\dfrac{1}{1-G(x)}
F(x)=1−G(x)1
多项式求逆。至于最后不足K的一段暴力卷积即可。
Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;++i)
#define fd(i,j,k) for(int i=j;i>=k;--i)
using namespace std;
typedef long long ll;
const int N=1e6+10,mo=998244353;
int qpow(int x,int y){
int s=1;
for(;y;y>>=1,x=(ll)x*x%mo) if(y&1) s=(ll)s*x%mo;
return s;
}
int pl(int x,int y){
return x+y>=mo?x+y-mo:x+y;
}
void inc(int &x,int y){
x=x+y>=mo?x+y-mo:x+y;
}
int rev[N*4],fn;
void NTT(int *a,int sig){
fo(i,1,fn-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int m=2;m<=fn;m<<=1){
int hf=m>>1,w0=qpow(3,(mo-1)/m);
if(sig<0) w0=qpow(w0,mo-2);
for(int i=0;i<fn;i+=m)
for(int j=i,w=1;j<i+hf;++j,w=(ll)w*w0%mo){
int u=a[j],v=(ll)a[j+hf]*w%mo;
a[j]=pl(u,v),a[j+hf]=pl(u,mo-v);
}
}
if(sig<0){
int nn=qpow(fn,mo-2);
fo(i,0,fn-1) a[i]=(ll)a[i]*nn%mo;
}
}
int c[N*4];
void inv(int ln,int *a,int *b){
if(ln==1){
b[0]=qpow(a[0],mo-2);
return;
}
inv((ln+1)>>1,a,b);
int cnt=0;
for(fn=1;fn<(ln<<1);fn<<=1) ++cnt;
fo(i,1,fn-1) rev[i]=rev[i>>1]>>1|(i&1)<<(cnt-1);
fo(i,0,ln-1) c[i]=a[i];
fo(i,ln,fn-1) c[i]=b[i]=0;
NTT(c,1),NTT(b,1);
fo(i,0,fn-1) b[i]=(2-(ll)c[i]*b[i]%mo+mo)%mo*b[i]%mo;
NTT(b,-1);
fo(i,ln,fn-1) b[i]=0;
}
int jc[N],ny[N];
int f[N*4],a[N],g[N];
int main()
{
freopen("interstellar.in","r",stdin);
freopen("interstellar.out","w",stdout);
int n,r,k,t;
scanf("%d %d %d",&n,&r,&k),t=n/k;
jc[0]=1;
fo(i,1,n) jc[i]=(ll)jc[i-1]*i%mo;
ny[n]=qpow(jc[n],mo-2);
fd(i,n,1) ny[i-1]=(ll)ny[i]*i%mo;
a[0]=1;
fo(i,1,t) a[i]=(mo-qpow(ny[i*k],r)*(i&1?1:-1))%mo,g[i]=mo-a[i];
inv(t+1,a,f);
int ans=0;
if(n%k){
fo(i,0,t){
ll w=(qpow(ny[n-i*k],r)*((t-i)&1?-1:1)+mo)%mo;
inc(ans,(ll)f[i]*w%mo);
}
}
else ans=f[t];
ans=(ll)ans*qpow(jc[n],r)%mo;
printf("%d",ans);
}