一道十分傻(jing)B(dian)的题目:
给定一有向图,边长均为
1
1
,求长度小于的环个数
modm
mod
m
。(点数小于等于
100
100
)。
倒是写了个很全的模板……
典型的水题…(矩阵套矩阵,分治两种做法都可以……后者常数非常小)
贴一个分治的代码(注意在分治的时候顺便处理出
Ak
A
k
):
# include <cctype>
# include <cstdio>
# include <cstring>
int MOD ;
# define RG register
# define N 101
class Matrix {
private :
int arr [N] [N] ;
public :
Matrix ( ) { memset ( arr, 0, sizeof arr ) ; }
inline void set ( ) { for ( int i = 0 ; i < N ; ++ i ) arr [i] [i] = 1 ; }
inline int* operator [] ( const int& u ) { return arr [u] ; }
inline Matrix operator * ( Matrix& ano ) const {
Matrix rt ;
for ( RG int k = 1 ; k < N ; ++ k )
for ( RG int i = 1 ; i < N ; ++ i )
if ( arr [i] [k] ) {
for ( RG int j = 1 ; j < N ; ++ j )
if ( ano [k] [j] ) {
rt [i] [j] += 1LL * arr [i] [k] * ano [k] [j] % MOD ;
if ( rt [i] [j] >= MOD ) rt [i] [j] -= MOD ;
}
}
return rt ;
}
inline void operator *= ( Matrix& ano ) {
Matrix rt ;
for ( RG int k = 1 ; k < N ; ++ k )
for ( RG int i = 1 ; i < N ; ++ i )
if ( arr [i] [k] ) {
for ( RG int j = 1 ; j < N ; ++ j )
if ( ano [k] [j] ) {
rt [i] [j] += 1LL * arr [i] [k] * ano [k] [j] % MOD ;
if ( rt [i] [j] >= MOD ) rt [i] [j] -= MOD ;
}
}
*this = rt ;
}
inline Matrix operator + ( Matrix& ano ) const {
Matrix rt ( *this ) ;
for ( RG int i = 0 ; i < N ; ++ i )
for ( RG int j = 0 ; j < N ; ++ j ) {
rt [i] [j] += ano [i] [j] ;
if ( rt [i] [j] >= MOD ) rt [i] [j] -= MOD ;
}
return rt ;
}
inline void operator += ( Matrix& ano ) {
for ( RG int i = 0 ; i < N ; ++ i )
for ( RG int j = 0 ; j < N ; ++ j ) {
arr [i] [j] += ano [i] [j] ;
if ( arr [i] [j] >= MOD ) arr [i] [j] -= MOD ;
}
}
inline Matrix operator ^ ( int x ) const {
Matrix rt, a ( *this ) ;
rt.set ( ) ;
for ( ; x ; a *= a, x >>= 1 )
if ( x & 1 ) {
rt *= a ;
}
return rt ;
}
} ;
Matrix A, B ;
inline Matrix S ( int n ) {
if ( n == 1 ) return B = A ;
Matrix rt, tmp ;
rt.set ( ) ;
tmp = S ( n >> 1 ) ;
rt += B ; // (base + A^ (n/2) ) * S ( n >> 1 )
rt *= tmp ; // B = A ^ ( n / 2 )
B *= B ;
if ( n & 1 ) {
B *= A ;
return rt + B ;
}
return rt ;
}
int main ( ) {
freopen ( "tour.in", "r", stdin ) ;
freopen ( "tour.out", "w", stdout ) ;
int n ;
scanf ( "%d", & n ) ;
for ( RG int i = 1 ; i <= n ; ++ i )
for ( RG int j = 1 ; j <= n ; ++ j ) {
static int c ;
while ( isspace ( c = getchar ( ) ) ) ;
if ( c == 'Y' ) A [i] [j] = 1 ;
}
int k, m ;
scanf ( "%d%d", & k, & m ) ;
MOD = m ;
Matrix rt = S ( k - 1 ) ;
long long ans ( 0 ) ;
for ( int i = 1 ; i <= n ; ++ i ) ans += rt [i] [i] ;
return ! printf ( "%d\n", ( int ) ( ans % m ) ) ;
}