问你用1-9拼一个mod x余k的数有多少种方法,
一开始脑抽了,从低位到高位做了(虽然这样做后发现是有循环规律的),但是发现异常难做,然后看了下题解原来是从高位往低位做了之后然后每次相当于余数乘十再加上1-9,所以构建余数矩阵f[i][(10*i)+x] += sum[x] 然后f矩阵做快速幂好了。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
long long f[110][110],ans[110][110],tmp[110][110];
int n,b,k,X,sum[11];
using namespace std;
void work(int x)
{
for (int i=0;i<X;i++)
ans[i][i]=1;
while (x)
{
if (x&1)
{
memset(tmp,0,sizeof(tmp));
for (int i=0;i<X;i++)
for (int j=0;j<X;j++)
for (int k=0;k<X;k++)
{
tmp[i][j]+=ans[i][k]*f[k][j];
tmp[i][j]=tmp[i][j]%(1000000007);
}
for (int i=0;i<X;i++)
for (int j=0;j<X;j++)
ans[i][j]=tmp[i][j];
}
memset(tmp,0,sizeof(tmp));
for (int i=0;i<X;i++)
for (int j=0;j<X;j++)
for (int k=0;k<X;k++)
{
tmp[i][j]+=f[i][k]*f[k][j];
tmp[i][j]=tmp[i][j]%(1000000007);
}
for (int i=0;i<X;i++)
for (int j=0;j<X;j++)
f[i][j]=tmp[i][j];
x=x>>1;
}
}
int main()
{
freopen("test.in","r",stdin);
memset(f,0,sizeof(f));
memset(ans,0,sizeof(ans));
int x;
scanf("%d%d%d%d",&n,&b,&k,&X);
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
sum[x]++;
}
for (int i=0;i<X;i++)
for (int j=1;j<=9;j++)
f[i][(i*10+j)%X]+=sum[j];
work(b);
printf("%d",ans[0][k]%1000000007);
return 0;
}