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

#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 ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值