美文网首页信息学竞赛题解(IO题解)数据结构和算法分析
BZOJ-2326: [HNOI2011]数学作业(矩阵快速幂)

BZOJ-2326: [HNOI2011]数学作业(矩阵快速幂)

作者: AmadeusChan | 来源:发表于2018-10-17 12:18 被阅读0次

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2326

    用矩阵乘法+快速幂乱搞一下就可以啦~~

    代码(之前由于代码中取了常用对数函数,结果T了N就,傻X地调了一个多小时QaQ):

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
     
    using namespace std ;
     
    #define ll long long 
    #define maxn 3
     
    ll n , mod ;
     
    struct mat {
         
        ll n , m , a[ maxn ][ maxn ] ;
         
        mat(  ) {
            memset( a , 0 , sizeof( a ) ) ;
        }
         
    } e , f , I ;
     
    mat operator * ( const mat &x , const mat &y ) {
        mat ret ;
        ret.n = x.n , ret.m = y.m ;
        for ( int i = 0 ; i < ret.n ; ++ i ) {
            for ( int j = 0 ; j < ret.m ; ++ j ) {
                for ( int k = 0 ; k < x.m ; ++ k ) {
                    ( ret.a[ i ][ j ] += x.a[ i ][ k ] * y.a[ k ][ j ] ) %= mod ;
                }
            }
        }
        return ret ;
    }
     
    mat pow( mat x , ll cnt ) {
        mat ret = I , rec = x ;
        for ( ; cnt ; cnt >>= 1 ) {
            if ( cnt & 1 ) ret = ret * rec ;
            rec = rec * rec ;
        }
        return ret ;
    }
     
    ll Exp[ 19 ] ;
     
    int search( ll x ) {
        if ( x < 10 ) return 1 ;
        if ( x == Exp[ 18 ] ) return 19 ;
        int l = 1 , r = 18 ;
        while ( r - l > 1 ) {
            int mid = ( l + r ) >> 1 ;
            if ( Exp[ mid ] <= x ) l = mid ; else r = mid ;
        }
        return r ;
    }
     
    int main(  ) {
        cin >> n >> mod ;
        Exp[ 0 ] = 1 ; for ( int i = 0 ; i ++ < 18 ; ) Exp[ i ] = Exp[ i - 1 ] * 10 ;
        f.n = 3 , f.m = 1 ;
        f.a[ 0 ][ 0 ] = f.a[ 1 ][ 0 ] = 0 , f.a[ 2 ][ 0 ] = 1 ;
        e.n = e.m = 3 ;
        e.a[ 0 ][ 1 ] = e.a[ 0 ][ 2 ] = e.a[ 1 ][ 1 ] = e.a[ 1 ][ 2 ] = e.a[ 2 ][ 2 ] = 1 ;
        I.n = I.m = 3 ;
        I.a[ 0 ][ 0 ] = I.a[ 1 ][ 1 ] = I.a[ 2 ][ 2 ] = 1 ;
        ll i = 1 ;
        while ( i <= n ) {
            int k = search( i ) ;
            ll pos = Exp[ k ] - 1 <= n ? Exp[ k ] - 1 : n ;
            e.a[ 0 ][ 0 ] = Exp[ k ] % mod ;
            f = pow( e , pos - i + 1 ) * f ;
            i = pos + 1 ;
        }
        cout << f.a[ 0 ][ 0 ] << endl ;
        return 0 ;
    }
    

    相关文章

      网友评论

        本文标题:BZOJ-2326: [HNOI2011]数学作业(矩阵快速幂)

        本文链接:https://www.haomeiwen.com/subject/gwglzftx.html