首先把权值化作下标
首先显然是要求
∏
(
1
+
x
a
i
)
\prod(1+x^{a_i})
∏(1+xai)一样的东西
这里的乘法是
k
k
k进制不进位加法卷积
显然是做
f
w
t
fwt
fwt
由于
998244353
998244353
998244353没有
w
5
,
w
6
w_5,w_6
w5,w6
手动扩域即可
考虑加起来做
f
w
t
fwt
fwt,然后再还原乘起来的
f
w
t
fwt
fwt点值
考虑高维
d
f
t
dft
dft时是一维一维的做
每一次都是乘
w
i
j
w^{ij}
wij
一个位置
a
a
a对
b
b
b的贡献是
w
∑
a
i
∗
b
i
w^{\sum a_i*b_i}
w∑ai∗bi
由于是
(
1
+
x
i
)
(1+x^i)
(1+xi)
所以最后一定是
(
1
+
w
k
p
)
(1+w_k^p)
(1+wkp)的形式
那么如果只把
(
x
a
i
)
(x^{a_i})
(xai)加起来做
f
w
t
fwt
fwt
最后一个位置
x
x
x有
f
x
,
t
f_{x,t}
fx,t个
w
k
t
w_k^t
wkt
就是说实际是
(
1
+
w
k
t
)
f
x
,
t
(1+w_k^t)^{f_{x,t}}
(1+wkt)fx,t
全部乘起来在
i
d
w
t
idwt
idwt回去即可
不用光速幂跑不过去。。。
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define fi first
#define ll long long
#define se second
#define bg begin
cs int RLEN=(1<<20)+1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(int bas=10){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=res*bas+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp&a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp&a,tp b){a>b?a=b:0;}
cs int mod=998244353;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b,a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(int x){return (x<0)?(x+mod):x;}
int tmp[12],k,n,m,lim;
cs int N=80000;
struct plx{
int a[6];
plx(){a[0]=a[1]=a[2]=a[3]=a[4]=a[5]=0;}
inline int &operator [](cs int &i){return a[i];}
inline cs int &operator [](cs int &i)cs{return a[i];}
friend inline plx operator +(plx a,plx b){
for(int i=0;i<k;i++)Add(a[i],b[i]);
return a;
}
friend inline plx operator -(plx a,plx b){
for(int i=0;i<k;i++)Dec(a[i],b[i]);
return a;
}
friend inline plx operator *(plx a,plx b){
for(int i=0;i<k;i++)if(a[i])for(int j=0;j<k;j++)
Add(tmp[i+j],mul(a[i],b[j]));
for(int i=0;i<k;i++)a[i]=add(tmp[i],tmp[i+k]),tmp[i]=tmp[i+k]=0;
return a;
}
inline int ans(){
if(k==5)return dec(a[0],a[1]);
else return add(dec(a[0],a[3]),mul(dec(add(a[1],a[5]),add(a[2],a[4])),Inv(2)));
}
}tp[6],f[N],w[6],pw1[6][1001],pw2[6][1001],I;
inline void init_w(){
for(int i=0;i<k;i++)w[i][i]=1;
for(int i=0;i<k;i++){
pw1[i][0]=pw2[i][0]=w[0];
pw1[i][1]=I+w[i];
for(int j=2;j<=1000;j++)pw1[i][j]=pw1[i][j-1]*pw1[i][1];
pw2[i][1]=pw1[i][1000];
for(int j=2;j<=1000;j++)pw2[i][j]=pw2[i][j-1]*pw2[i][1];
}
}
inline void dwt(plx *f,int lim){
for(int mid=1;mid<lim;mid*=k)
for(int i=0;i<lim;i+=mid*k)
for(int j=0;j<mid;j++){
for(int l=0;l<k;l++)tp[l]=f[i+l*mid+j];
for(int p=0;p<k;p++){
int ps=i+p*mid+j;
f[ps]=plx();
for(int l=0;l<k;l++)
f[ps]=f[ps]+w[l*p%k]*tp[l];
}
}
}
inline void idwt(plx *f,int lim){
for(int mid=1;mid<lim;mid*=k)
for(int i=0;i<lim;i+=mid*k)
for(int j=0;j<mid;j++){
for(int l=0;l<k;l++)tp[l]=f[i+l*mid+j];
for(int p=0;p<k;p++){
int ps=i+p*mid+j;
f[ps]=plx();
for(int l=0,o;l<k;l++)
o=l*p%k,f[ps]=f[ps]+w[o?(k-o):0]*tp[l];
}
}
for(int i=0,iv=Inv(lim);i<lim;i++)
for(int j=0;j<k;j++)Mul(f[i][j],iv);
}
inline plx pksm(plx a,int b){
plx ret=I;
for(;b;b>>=1,a=a*a)if(b&1)ret=ret*a;
return ret;
}
inline plx get(plx x){
plx ret=I;
for(int i=0;i<k;i++){
ret=ret*pw1[i][x[i]%1000]*pw2[i][x[i]/1000];
}
return ret;
}
int main(){
#ifdef Stargazer
freopen("lx.cpp","r",stdin);
freopen("my.out","w",stdout);
#endif
n=read(),k=read(),m=read();
I[0]=1,lim=ksm(k,m),init_w();
for(int i=1;i<=n;i++)f[read(k)][0]++;
dwt(f,lim);
for(int i=0;i<lim;i++)f[i]=get(f[i]);
idwt(f,lim);int ret=0;
for(int i=0;i<lim;i++)cout<<f[i].ans()<<'\n';//Add(ret,mul(mul(i,i),f[i].ans()));
}