传送门:
http://codeforces.com/problemset/problem/621/E
题意:给出n,b,k,x,每个盒子里有n个数,有b个盒子,从每个盒子中随机选出一个数(必选),使得形成的大数modx==k。
b是10的9次幂,这题其实一看就是dp加矩阵快速幂,当时比赛的时候过的人数就比D题多,就感觉肯定是道模型水题,其实之前我的博客里面就有一道类似的题,而且这道题目还比那道题要水的多。
还是一样,矩阵的i行j列表示的就是,从余数为i到余数为j的可能方法数,注意这道题是取模,因此需要叠加,然后因为每次状态转移都是一样的,所以快速幂就可以了 ,这里是用递归写的快速幂,也是蛮方便的。最后输出就是由余数为0到余数为k的方法数就可以了
(0到k,可以是0到1,1到k,0到2….)
b就是幂次,多么水的题啊!!!!
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
int freq[10],x;
ll P=1000000007;
struct matrix
{
ll arr[100][100];
};
matrix mul(matrix a,matrix b)
{
matrix c;
for(int i=0;i<x;i++)
for(int j=0;j<x;j++)
{
c.arr[i][j]=0;
for(int k=0;k<x;k++)
c.arr[i][j]=(c.arr[i][j]+(a.arr[i][k]*b.arr[k][j])%P)%P;
}
return c;
}
matrix T,I;
matrix mpow(matrix X,int power)
{
if(power==0)return I;
if(power==1)return T;
matrix tmp;
if(power&1)
tmp=mpow(X,power-1),tmp=mul(tmp,X);
else
tmp=mpow(X,power>>1),tmp=mul(tmp,tmp);
return tmp;
}
int main()
{
cin.sync_with_stdio(0);
int n,b,k,d;
cin>>n>>b>>k>>x;
for(int i=0;i<n;i++)cin>>d,freq[d]++;
for(int i=0;i<x;i++)
{I.arr[i][i]=1;
for(int j=1;j<=9;j++)
T.arr[i][(i*10+j)%x]=(T.arr[i][(i*10+j)%x]+freq[j])%P;}
T=mpow(T,b);
cout<<T.arr[0][k]<<"\n";
return 0;
}