题目大意:
给你N个数,b个块,每个块都是n个数,且都一样,现在让你从每个块取一个数,并且按序拼接在一起之后%x==k的方案数。
按序拼接:第一个块取的数是i,第二个块取得数是j,第三个块取的数是k,那么按序拼接在一起得到的数就是ijk.
思路:
1、
统计方案数,考虑dp,不难想到设定dp【i】【j】表示进行到第i个块,所取数据%x==j的方案数。
那么就有:
dp【i】【(j*10+l)%m】+=dp【i-1】【j】*num【l】.表示当前这个块取了数字l拼接到最后的方案数转移情况。
观察到b有1e9辣么大。那么可以使用矩阵快速幂进行优化。
2、矩阵的设定:
对于第一个矩阵中的数据,要根据实际情况决定。
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
#define mod 1000000007
#define ll __int64
typedef struct Matrix
{
ll mat[102][102];
}matrix;
matrix A,B,tmp;
ll num[15];
ll n,b,x,m;
Matrix matrix_mul(matrix a,matrix b)
{
matrix c;
memset(c.mat,0,sizeof(c.mat));
ll i,j,k;
for(ll i=0;i<m;i++)
{
for(ll j=0;j<m;j++)
{
for(ll k=0;k<m;k++)
{
c.mat[i][j]=(c.mat[i][j]+(a.mat[i][k]*b.mat[k][j])%mod)%mod;
}
}
}
return c;
}
Matrix matrix_quick_power(matrix a,ll k)//矩阵快速幂0.0
{
matrix b;
memset(b.mat,0,sizeof(b.mat));
for(ll i=0;i<m;i++)
b.mat[i][i]=1;//单位矩阵b
while(k)
{
if(k%2==1)
{
b=matrix_mul(a,b);
k-=1;
}
else
{
a=matrix_mul(a,a);
k/=2;
}
}
return b;
}
int main()
{
while(~scanf("%I64d%I64d%I64d%I64d",&n,&b,&x,&m))
{
memset(tmp.mat,0,sizeof(tmp.mat));
memset(A.mat,0,sizeof(A.mat));
memset(num,0,sizeof(num));
for(ll i=1;i<=n;i++)
{
ll x;scanf("%I64d",&x);
num[x]++;
}
for(ll i=0;i<m;i++)
{
for(ll j=0;j<m;j++)
{
for(ll l=1;l<=9;l++)
{
ll tmpnum=j*10+l;
tmpnum%=m;
if(tmpnum==i)
{
A.mat[i][j]+=num[l];
}
}
}
}
for(ll i=0;i<m;i++)
{
for(ll j=1;j<=9;j++)
{
if(j%m==i)
{
tmp.mat[i][0]+=num[j];
}
}
}
B=matrix_quick_power(A,b-1);
B=matrix_mul(B,tmp);
printf("%I64d\n",B.mat[x][0]);
}
}