- 面对形如\(f_j \cdot g_{j-i}\)的“差卷积”,可以通过倒置数组的方法凑出卷积的形式
#include <bits/stdc++.h>
#define int long long
using namespace std;
const signed mod=1004535809;
int w[100005],f[100005],g[100005];
int power(int n,int p)
{
if(p==0)
{
return 1;
}
long long tmp=power(n,p/2);
if(p%2==1)
{
return tmp*tmp%mod*n%mod;
}
return tmp*tmp%mod;
}
long long jc[10000005],jcinv[10000005];
void pre()
{
jc[0]=1;
for(int i=1;i<=10000000;i++)
{
jc[i]=jc[i-1]*i%mod;
}
jcinv[10000000]=power(jc[10000000],mod-2);
for(int i=10000000-1;i>=0;i--)
{
jcinv[i]=jcinv[i+1]*(i+1)%mod;
}
}
long long c(int n,int m)
{
if(m>n)
{
return 0;
}
return jc[n]*jcinv[m]%mod*jcinv[n-m]%mod;
}
typedef vector<int> poly;
int rev[5000005],p[5000005][2];
void NTT(poly &f,int opt)
{
int n=f.size();
for(int i=1;i<n;i++)
{
if(i<rev[i])
{
swap(f[i],f[rev[i]]);
}
}
for(int m=2;m<=n;m*=2)
{
int k=m/2;
for(int i=0;i<n;i+=m)
{
long long cur=1,step;
if(opt==1)
{
step=p[m][0];
}
else
{
step=p[m][1];
}
for(int j=0;j<k;j++)
{
long long tmp=cur*f[i+j+k]%mod;
f[i+j+k]=(f[i+j]-tmp)%mod;
f[i+j]=(f[i+j]+tmp)%mod;
cur=cur*step%mod;
}
}
}
}
poly operator*(poly a,poly b)
{
poly c(a.size()+b.size()-1);
int p=0;
while((1<<p)<c.size())
{
p++;
}
for(int i=1;i<(1<<p);i++)
{
rev[i]=(rev[i>>1]>>1);
if(i&1)
{
rev[i]+=(1<<(p-1));
}
}
c.resize(1<<p);
a.resize(c.size());
b.resize(c.size());
NTT(a,1),NTT(b,1);
for(int i=0;i<c.size();i++)
{
c[i]=a[i]*b[i]%mod;
}
NTT(c,-1);
p=power(c.size(),mod-2);
for(int i=0;i<c.size();i++)
{
c[i]=c[i]*p%mod;
}
return c;
}
void ntt_pre()
{
for(int i=1;i<=20;i++)
{
p[1<<i][0]=power(3,(mod-1)/(1<<i));
p[1<<i][1]=power(3,(mod-1)-(mod-1)/(1<<i));
}
}
void fac(int x)
{
int p[15]={0},c[15]={0},tot=0;
int i=2;
while(i*i<=x)
{
if(x%i==0)
{
tot++;
p[tot]=i;
while(x%i==0)
{
c[tot]++;
x/=i;
}
}
i++;
}
if(x>1)
{
tot++;
p[tot]=x;
c[tot]=1;
}
for(int i=1;i<=tot;i++)
{
cout<<p[i]<<" "<<c[i]<<endl;
}
}
ostream& operator <<(ostream& os,vector<int> x)
{
for(int i:x)
{
os<<(i+mod)%mod;
os<<' ';
}
return os;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
pre();
ntt_pre();
int n,m,s;
cin>>n>>m>>s;
for(int i=0;i<=m;i++)
{
cin>>w[i];
}
for(int i=0;i<=m&&i*s<=n;i++)
{
g[i]=c(m,i)*c(n,i*s)%mod*power(m-i,n-i*s)%mod*jc[i*s]%mod*power(jcinv[s],i)%mod*jc[i]%mod;
}
reverse(g,g+m+1);
poly F,G(m+1),H(m+1);
for(int i=0;i<=m;i++)
{
G[i]=g[i];
H[i]=jcinv[i];
if(i%2)
{
H[i]=-H[i];
}
}
F=G*H;
F.resize(m+1);
reverse(F.begin(),F.end());
int ans=0;
for(int i=0;i<=m&&i*s<=n;i++)
{
F[i]=F[i]*jcinv[i]%mod;
ans=(ans+F[i]*w[i]%mod)%mod;
}
cout<<(ans+mod)%mod<<endl;
return 0;
}