Codeforces Round #341 (Div. 2) E. Wet Shark and Blocks

来源:互联网 发布:好用的cms 编辑:程序博客网 时间:2024/05/16 18:22
E. Wet Shark and Blocks
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are b blocks of digits. Each one consisting of the samen digits, which are given to you in the input. Wet Shark must chooseexactly one digit from each block and concatenate all of those digits together to form one large integer. For example, if he chooses digit1 from the first block and digit 2 from the second block, he gets the integer 12.

Wet Shark then takes this number modulo x. Please, tell him how many ways he can choose one digit from each block so that he gets exactlyk as the final result. As this number may be too large, print it modulo109 + 7.

Note, that the number of ways to choose some digit in the block is equal to the number of it's occurrences. For example, there are3 ways to choose digit 5 from block3 5 6 7 8 9 5 1 1 1 1 5.

Input

The first line of the input contains four space-separated integers, n, b, k and x (2 ≤ n ≤ 50 000, 1 ≤ b ≤ 109, 0 ≤ k < x ≤ 100, x ≥ 2) — the number of digits in one block, the number of blocks, interesting remainder modulo x and modulox itself.

The next line contains n space separated integersai (1 ≤ ai ≤ 9), that give the digits contained in each block.

Output

Print the number of ways to pick exactly one digit from each blocks, such that the resulting integer equalsk modulo x.

Examples
Input
12 1 5 103 5 6 7 8 9 5 1 1 1 1 5
Output
3
Input
3 2 1 26 2 2
Output
0
Input
3 2 1 23 1 2
Output
6
Note

In the second sample possible integers are 22, 26, 62 and 66. None of them gives the remainder1 modulo 2.

In the third sample integers 11, 13, 21, 23, 31 and 33 have remainder 1 modulo 2. There is exactly one way to obtain each of these integers, so the total answer is6.

【题意】一个块中有n个数字,一共有b个块,每个块里的n个数字一模一样,现在在每个块中选一个数字,然后首尾串成一个大整数,把这个整数取模x,问有多少种情况最后的结果恰好等于k?

【分析】如果不考虑b的大小,我们能想到数位dp,dp[k][(i*10+j)%x]+=dp[k-1][i]*num[j]  (1<=j<=9),dp[k][i]表示现在正在考虑前k个块,此时结果取模x等于i的方案数。

但是我们发现,b实在是太大了,那么该怎么办呢?我们可以容易发现dp的转移其实就是构造的这个矩阵的自乘,所以我们可以用矩阵快速幂。

【AC 代码】

////Created by just_sort 2016/9/9 12:38//All Rights Reserved//#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const LL mod = 1e9+7;struct Matrix{    int row,col;    LL mat[105][105];    void init(int row,int col,bool ok=false){        this->row=row,this->col=col;        memset(mat,0,sizeof(mat));        if(!ok) return ;        for(int i=0; i<row; i++) mat[i][i]=1;    }    Matrix operator*(const Matrix &rhs){        Matrix ret;ret.init(row,rhs.col);        for(int k=0; k<col; k++){            for(int i=0; i<row; i++){                if(mat[i][k]==0) continue;                for(int j=0; j<rhs.col; j++){                    if(rhs.mat[k][j]==0) continue;                    ret.mat[i][j]+=mat[i][k]*rhs.mat[k][j]%mod;                    ret.mat[i][j]%=mod;                }            }        }        return ret;    }    Matrix operator^(LL n){        Matrix ret,x=*this;        ret.init(row,col,1);        while(n){            if(n&1) ret=ret*x;            x=x*x;            n>>=1;        }        return ret;    }}A;int n,b,k,x;int cnt[10];int main(){    cin>>n>>b>>k>>x;    memset(cnt,0,sizeof(cnt));    for(int i=1; i<=n; i++){        int v;        cin>>v;        cnt[v]++;    }    //get matrix    A.init(x,x);    for(int i=0; i<x; i++){        for(int j=0; j<10; j++){            A.mat[i][(i*10+j)%x]+=cnt[j];        }    }    Matrix ans=A^b;//    for(int i=0; i<ans.row; i++){//        for(int j=0; j<ans.col; j++){//            printf("%lld ",ans.mat[i][j]);//        }//        puts("");//    }    printf("%lld\n",ans.mat[0][k]);    return 0;}



0 0
原创粉丝点击