BZOJ 2326 数学作业

Posted xgtao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2326 数学作业相关的知识,希望对你有一定的参考价值。

题意:

给出一个数字N(1e18),求1 ~ N 的数字排起来mod上M(<= 1e9)的值。

 

题解:

0.定义f[x]表示以数字x结尾的数字mod 上 M 的值。

1.

  f[x] = f[x-1] * 10 + x - 1 + 1 x为个位数的情况

  f[x] = f[x-1] * 100 + x - 1 + 1 x为两位数的情况

  f[x] = f[x-1] * 1000 + x - 1 + 1 x为三位数的情况

  ......

2.这样就可以对不同位数的数建立矩阵进行加速转移

技术分享

 

/**************************************************************
    Problem: 2326
    User: xgtao
    Language: C++
    Result: Accepted
    Time:24 ms
    Memory:1288 kb
****************************************************************/
 
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
 
#define ll long long
ll mod, n, pow[25];
 
struct Matrix {
    ll map[3][3];
    void clear () { memset (map, 0, sizeof (map));}
};
 
Matrix MatrixMul (Matrix x, Matrix y) {
    Matrix ret;
    ret.clear();
    for (int i = 0; i < 3; ++i) 
        for (int j = 0;j < 3; ++j)
            for (int k = 0; k < 3; ++k)
                ret.map[i][j] = (ret.map[i][j] + x.map[i][k] * y.map[k][j] % mod) % mod;
    return ret;
}
 
Matrix MatrixPow (Matrix x, ll n) {
    Matrix ret;
    ret.clear();
    ret.map[0][0] = ret.map[1][1] = ret.map[2][2] = 1;
    while (n) {
        if (n & 1) ret = MatrixMul(ret, x);
        x = MatrixMul(x, x);
        n >>= 1;
    }
    return ret;
}
 
Matrix calc (ll x, ll n) {
    Matrix ret;
    ret.clear();
    ret.map[0][0] = x % mod;
    ret.map[0][1] = 0;
    ret.map[0][2] = 0;
    ret.map[1][0] = 1;
    ret.map[1][1] = 1;
    ret.map[1][2] = 0;
    ret.map[2][0] = 1;
    ret.map[2][1] = 1;
    ret.map[2][2] = 1;
    return MatrixPow(ret, n);
}
 
int main () {
    pow[0] = 1;
    for (int i = 1; i <= 18; ++i) pow[i] = pow[i - 1] * 10;
    cin >> n >> mod;
    int cur = 1;
    Matrix ans;
    ans.clear();
    ans.map[0][0] = ans.map[1][1] = ans.map[2][2] = 1;
    while (true) {
        ll L = pow[cur - 1], R = min (n, pow[cur] - 1);
        ans = MatrixMul (ans, calc(pow[cur], R - L + 1));
        ++cur;
        if (R == n) break;
    }
    cout << ans.map[2][0] << endl;
    return 0;
}

  

 

以上是关于BZOJ 2326 数学作业的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2326 数学作业

BZOJ2326: [HNOI2011]数学作业

BZOJ2326[HNOI2011]数学作业 矩阵乘法

bzoj 2326: [HNOI2011]数学作业

bzoj 2326HNOI 2011数学作业

BZOJ 2326 数学作业