程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> BZOJ 2326 HNOI 2011 數學作業 矩陣乘法

BZOJ 2326 HNOI 2011 數學作業 矩陣乘法

編輯:關於C++

題目大意

求一個這樣的數:“12345678910111213……”對m取模的值。

思路

觀察這個數字的特點,每次向後面添加一個數。也就是原來的數乘10^k之後在加上一個數。而且處理每個數量級的時候是相似的。所以就可以用矩陣乘法來加速。我構造的矩陣是這樣的。
[當前數字累加數字1]×???數量級10011001???=[新的數字累加數字+11]

CODE

#include 
#include 
#include 
#include 
#define MO p
using namespace std;

long long k,p;

struct Matrix{
    long long num[5][5];
    int w,h;

    Matrix(int _,int __):w(_),h(__) {
        memset(num,0,sizeof(num));
    }
    Matrix() {
        memset(num,0,sizeof(num));
    }
    Matrix operator *(const Matrix &a)const {
        Matrix re(w,a.h);
        for(int i = 1; i <= w; ++i)
            for(int j = 1; j <= a.h; ++j)
                for(int k = 1; k <= h; ++k)
                    re.num[i][j] = (re.num[i][j] + num[i][k] * a.num[k][j] % MO) % MO;
        return re;
    }
};

inline Matrix QuickPower(Matrix a,long long k)
{
    Matrix re(3,3);
    re.num[1][1] = re.num[2][2] = re.num[3][3] = 1;
    while(k) {
        if(k&1) re = re * a;
        a = a * a;
        k >>= 1;
    }
    return re;
}

int main()
{
    cin >> k >> p;
    long long now = 10,ans_num = 0;
    while(k >= now - now / 10 && now < 1e18) {
        k -= now - now / 10;
        Matrix right(3,3);
        right.num[1][1] = now % MO;
        right.num[2][1] = right.num[2][2] = right.num[3][2] = right.num[3][3] = 1;
        right = QuickPower(right,now - now / 10);
        Matrix left(1,3);
        left.num[1][1] = ans_num;
        left.num[1][2] = (now / 10) % MO;
        left.num[1][3] = 1;
        ans_num = (left * right).num[1][1];
        now *= 10;
    }
    Matrix right(3,3);
    right.num[1][1] = now % MO;
    right.num[2][1] = right.num[2][2] = right.num[3][2] = right.num[3][3] = 1;
    right = QuickPower(right,k);
    Matrix left(1,3);
    left.num[1][1] = ans_num;
    left.num[1][2] = (now / 10) % MO;
    left.num[1][3] = 1;
    cout << (left * right).num[1][1] << endl;
    return 0;
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved