BZOJ2326 [HNOI2011]数学作业(分块矩阵快速幂)

题意:

定义函数Concatenate (1 ..N)是将所有正整数 1, 2, …, N 顺序连接起来得到的数,如concatenate(1..5)是12345,求concatenate(1...n)%m的值

思路:

 矩阵快速幂,公式为

$$
\left[
\begin{matrix}
f(n)\\n\\1
\end{matrix}
\right]=
\left[
\begin{matrix}
10^k&1&1\\
0&1&1\\
0&0&1
\end{matrix}
\right]
\left[
\begin{matrix}
f(n-1)\\n-1\\1
\end{matrix}
\right]
$$

其中$10^k$可以分快处理,分n为0~9,10~99,100~999等

代码:

/**************************************************************
    Problem: 2326
    User: wrjlinkkkkkk
    Language: C++
    Result: Accepted
    Time:64 ms
    Memory:1292 kb
****************************************************************/
 
#include<iostream>
#include<iomanip> 
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
#include<list>
     
#define fst first
#define sc second
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) 
#pragma Gcc optimize(2)
 
using namespace std;
 
typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;
 
 
const int maxn = 10000 + 100;
const int maxm = 5e3 + 100;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
int scan(){
    int res=0,ch,flag=0;
    if((ch=getchar())=='-')
        flag=1;
    else if(ch>='0'&&ch<='9')
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}
 
ll n, m;
 
ll mul(ll x,ll y){
    ll s=0;
    while(y)
    {
        if(y&1)s=(s+x)%m;
        x=(x<<1)%m;
        y>>=1;
    }
    return s;
}
void mtpl(ll a[4][4], ll b[4][4],ll s[4][4]){
    ll tmp[4][4];
    for(int i = 1; i <= 3; i++){
        for(int j = 1; j <= 3; j++){
            tmp[i][j]=0;
            for(int k = 1; k <= 3; k++){
                tmp[i][j] += mul(a[i][k] , b[k][j])%m;
            }
             
        }
         
    }
    for(int i = 1; i <= 3; i++){
        for(int j = 1; j <= 3; j++){
            s[i][j] = tmp[i][j];
        }
    }
    return;
}
ll b[4][4];
void Fast_power(ll t,ll last){
    ll a[4][4];
    mem(a, 0);
    a[1][1] = t;
    a[2][1] = a[3][1] = a[2][2] = a[3][2] = a[3][3] = 1;
    ll y = last-t/10+1;
    while(y){
        if(y & 1) mtpl(b, a, b);
        mtpl(a, a, a);
        y >>= 1;
    }
    //prt(ans);
    return;
}
int main(){
 
    scanf("%lld %lld", &n, &m);
 
     
    mem(b, 0);
    for(int i = 1; i <= 3; i++)b[i][i] = 1;
    ll t = 10;
    while(t <= n){
        Fast_power(t, t-1);
        t*=10;
         
    }
    Fast_power(t,n);
    printf("%lld", b[3][1]%m);
    return 0;
}
/*
8 3287492749272074
*/

 

posted @ 2018-08-13 15:17  wrjlinkkkkkk  阅读(285)  评论(0编辑  收藏  举报