zoukankan      html  css  js  c++  java
  • 【HNOI2011】数学作业(BZOJ 2326)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2326   设f[i]表示i的答案,那么 f[i] = f[i - 1] * 10 + i      (i < 10) f[i] = f[i - 1] * 100 + i    (  100<=i<=999) ……   我们发现N的范围很大所以要用矩阵加速递推: 然后也需要分段改变递推矩阵的系数。  
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define MID(x,y) ((x+y)>>1)
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    
    typedef long long LL;
    
    LL n, m;
    const int MAX = 5;
    struct Mat{
        int row, col;
        LL mat[MAX][MAX];
    };
    //initialize square matrix to unit matrix
    Mat unit(int n){
        Mat A;
        A.row = A.col = n;
        memset(A.mat, 0, sizeof(A.mat));
        for (int i = 0; i < n; i ++)
            A.mat[i][i] = 1;
        return A;
    }
    //return A*B%mod
    Mat mul(Mat A, Mat B, int mod){
        Mat C;
        C.row = A.row;
        C.col = B.col;
        for (int i = 0; i < A.row; i ++){
            for (int j = 0; j < B.col; j ++){
                C.mat[i][j] = 0;
                for (int k = 0; k < A.col; k ++)
                    //注意这里要保证乘法不溢出,否则还需要设计特殊的乘法模
                    C.mat[i][j] += A.mat[i][k] * B.mat[k][j];
                C.mat[i][j] %= mod;
            }
        }
        return C;
    };
    //return A^n%mod
    Mat exp_mod(Mat A, LL n, int mod){
        Mat res = unit(A.row);
        while(n){
            if (n & 1LL){
                res = mul(res, A, mod);
            }
            A = mul(A, A, mod);
            n >>= 1;
        }
        return res;
    }
    Mat A, res;
    
    void changeA(LL p){
        A.col = A.row = 3;
        A.mat[0][0] = p % m;   A.mat[0][1] = 1;    A.mat[0][2] = 0;
        A.mat[1][0] = 0;    A.mat[1][1] = 1;    A.mat[1][2] = 1;
        A.mat[2][0] = 0;    A.mat[2][1] = 0;    A.mat[2][2] = 1;
    }
    
    void init(){
        res.col = 1;
        res.row = 3;
        res.mat[0][0] = 0;
        res.mat[1][0] = 1;
        res.mat[2][0] = 1;
        changeA(10);
    }
    
    int main(){
        cin >> n >> m;
        init();
        LL k1 = 0;
        LL k2 = 9;
        LL ct = 10;
        while(n >= k2){
            res = mul(exp_mod(A, k2-k1, m), res, m);
            k1 = k2;
            if (k2 == 99999999999999999)
                k2 = 100000000000000001;
            k2 = k2 * 10 + 9;
            changeA(10*ct);
            ct *= 10;
        }
        if (n > k1)
            res = mul(exp_mod(A, n-k1, m), res, m);
        cout << res.mat[0][0] << endl;
    	return 0;
    }
    
     
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    八卦——朋友的老公有外遇
    吃,玩——幸福的上海一天
    婚礼——金茂群楼豪华婚礼
    吃狂吃大喜九
    玩——苏州粗体验
    XCF之原形
    快速类型判定
    ReaderWriterLockSlim使用注意事项
    WCF服务端基于配置的实现——路由
    Opera使用心得
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114014.html
Copyright © 2011-2022 走看看