题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1009
我们设f(i,j)为原串中匹配到第i为,不吉利号码匹配到第j位的数目,那么我们可以用矩阵来表示状态转移方程为:
a矩阵用KMP算法来预处理,然后用矩阵快速幂即可。
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std ;
#define rep( i , x ) for ( int i = 0 ; i < x ; ++ i )
#define MAXN 25
struct mat {
int a[ MAXN ][ MAXN ] , n , m ;
mat( ) {
n = m = 0 ;
memset( a , 0 , sizeof( a ) ) ;
}
void I( int _n ) {
n = m = _n ;
rep( i , n ) a[ i ][ i ] = 1 ;
}
} ori , ans ;
int mod ;
mat operator * ( const mat &x , const mat &y ) {
mat ret ;
ret.n = x.n , ret.m = y.m ;
rep( i , ret.n ) rep( j , ret.m ) rep( k , x.m ) {
( ret.a[ i ][ j ] += x.a[ i ][ k ] * y.a[ k ][ j ] ) %= mod ;
}
return ret ;
}
mat power( mat x , int cnt ) {
mat ret ; ret.I( x.n ) ;
for ( ; cnt ; cnt >>= 1 ) {
if ( cnt & 1 ) ret = ret * x ;
x = x * x ;
}
return ret ;
}
int n , m , s[ MAXN ] ;
int pre[ MAXN ] ;
void kmp( ) {
memset( pre , 0 , sizeof( pre ) ) ;
for ( int i = 1 , j = 0 ; i ++ < m ; ) {
for ( ; j && s[ i ] != s[ j + 1 ] ; j = pre[ j ] ) ;
if ( s[ j + 1 ] == s[ i ] ) ++ j ;
pre[ i ] = j ;
}
}
int main( ) {
scanf( "%d%d%d" , &n , &m , &mod ) ;
for ( int i = 0 ; i ++ < m ; ) {
int ch ; for ( ch = getchar( ) ; ! ( ch >= '0' && ch <= '9' ) ; ch = getchar( ) ) ;
s[ i ] = ch - '0' ;
}
kmp( ) ;
ori.n = ori.m = m ;
rep( i , m ) {
rep( j , 10 ) {
int k ;
for ( k = i ; k && s[ k + 1 ] != j ; k = pre[ k ] ) ;
if ( s[ k + 1 ] == j ) ++ k ;
if ( k < m ) ++ ori.a[ k ][ i ] ;
}
}
ans.n = m , ans.m = 1 ;
ans.a[ 0 ][ 0 ] = 1 ;
ans = power( ori , n ) * ans ;
int Ans = 0 ;
rep( i , m ) ( Ans += ans.a[ i ][ 0 ] ) %= mod ;
printf( "%d\n" , Ans ) ;
return 0 ;
}