zoukankan      html  css  js  c++  java
  • bzoj2326 [HNOI2011]数学作业

    bzoj2326 [HNOI2011]数学作业

    求将 (1)(n) 的所有整数顺序连接得到的数模 (m) 的值

    (nleq10^{18}, mleq10^9)

    矩阵加速


    首先得到 (f_i=10^{lfloor log_{10}i floor} imes f_{i-1}+i)

    形如 (f_i=k imes f_{i-1}+i) 的式子显然可以矩阵加速,即表示为 $$egin{bmatrix}f_i&i&1end{bmatrix}egin{bmatrix}k&0&01&1&01&1&1end{bmatrix}=egin{bmatrix}f_{i+1}&i+1&1end{bmatrix}$$

    又因为 (10^{lfloorlog_{10}i floor}) 的取值只有 (18) 种,于是可以将每种取值分类讨论

    即求出后 (f_{10^a-1}) 通过矩阵 (egin{bmatrix}10^{a+1}&0&0\1&1&0\1&1&1end{bmatrix}) 快速转移至 (f_{10^{a+1}-1}) ,多出来的部分同理计算即可

    计算过程可能会爆 (long long) ……

    时间复杂度 (O(log_{10}{n} imeslog_2n))

    代码(码风极丑……

    #include <bits/stdc++.h>
    using namespace std;
    
    #define rep(i) for (int i = 0; i < 3; i++)
    typedef long long ll;
    ll n; int P;
    
    struct matrix {
      int arr[3][3];
    
      matrix() { memset(arr, 0, sizeof arr); }
    
      int* operator [] (const int& pos) {
        return arr[pos];
      }
    } E, M;
    
    inline int inc(int x, int y) {
      return x + y < P ? x + y : x + y - P;
    }
    
    matrix operator + (matrix a, matrix b) {
      rep(i) rep(j) a[i][j] = inc(a[i][j], b[i][j]);
      return a;
    }
    
    matrix operator * (matrix a, matrix b) {
      matrix res;
      rep(k) rep(i) rep(j) {
        res[i][j] = inc(res[i][j], 1ll * a[i][k] * b[k][j] % P);
      }
      return res;
    }
    
    matrix qp(matrix a, ll k) {
      matrix res = E;
      for (; k; k >>= 1, a = a * a) {
        if (k & 1) res = res * a;
      }
      return res;
    }
    
    int main() {
      E[0][0] = E[1][1] = E[2][2] = 1;
      M[1][0] = M[1][1] = M[2][0] = M[2][1] = M[2][2] = 1;
      scanf("%lld %d", &n, &P);
      int f[15];
      f[0] = 0;
      for (int i = 1; i < 10; i++) {
        f[i] = (10ll * f[i - 1] + i) % P;
      }
      if (n < 10) {
        printf("%d", f[n]);
        return 0;
      }
      matrix A;
      unsigned long long now = 10;
      A[0][0] = f[9], A[0][1] = 9, A[0][2] = 1;
      for (; now * 10 - 1 <= n; now *= 10) {
        M[0][0] = now * 10 % P;
        A = A * qp(M, now * 9);
      }
      M[0][0] = now * 10 % P;
      A = A * qp(M, n - now + 1);
      printf("%d", A[0][0]);
      return 0;
    }
    
  • 相关阅读:
    vue2 v-model/v-text 中使用过滤器的方法示例
    HTML5游戏开发案例教程合集
    Docker实战案例视频课程
    Java项目框架架构与优化教程
    Linux云计算-虚拟化技术视频教程
    udl
    Chloe官网及基于NFine的后台源码毫无保留开放
    抽象类存在的意义和作用
    Shell 脚本语法
    Github 高级搜索功能
  • 原文地址:https://www.cnblogs.com/Juanzhang/p/10786368.html
Copyright © 2011-2022 走看看