[HNOI 2011] 数学作业
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=2326
[算法]
.矩阵乘法即可
时间复杂度 : O(logN)
[代码]
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; ll n; int m; int mat[4][4]; ll pw[20]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline int len(ll x) { int ret = 0; while (x > 0) ++ret , x /= 10; return ret; } inline void multipy(int a[4][4] , int b[4][4]) { int ret[4][4]; memset(ret , 0 , sizeof(ret)); for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { for (int k = 1; k <= 3; k++) { ret[i][j] = (ret[i][j] + 1ll * a[i][k] % m * b[k][j] % m) % m; } } } for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { a[i][j] = ret[i][j]; } } } inline void exp_mod(int base[4][4] , ll n) { int ret[4][4]; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { ret[i][j] = (i == j); } } while (n > 0) { if (n & 1) multipy(ret , base); multipy(base , base); n >>= 1; } for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { base[i][j] = ret[i][j]; } } } int main() { read(n); read(m); int L = len(n); pw[0] = 1; for (int i = 1; i <= L; i++) pw[i] = pw[i - 1] * 10; int ans = 0; for (int i = 1; i < L; i++) { mat[1][1] = (1ll * pw[i] % m); mat[1][2] = 1; mat[1][3] = 0; mat[2][1] = 0; mat[2][2] = 1; mat[2][3] = 1; mat[3][1] = 0; mat[3][2] = 0; mat[3][3] = 1; exp_mod(mat , pw[i] - pw[i - 1]); ans = (1ll * mat[1][1] % m * ans % m + 1ll * mat[1][2] % m * (pw[i - 1] % m) + mat[1][3] % m) % m; } mat[1][1] = pw[L] % m; mat[1][2] = 1; mat[1][3] = 0; mat[2][1] = 0; mat[2][2] = 1; mat[2][3] = 1; mat[3][1] = 0; mat[3][2] = 0; mat[3][3] = 1; exp_mod(mat , n - pw[L - 1] + 1); ans = (1ll * mat[1][1] * ans % m + 1ll * mat[1][2] * (pw[L - 1] % m) + mat[1][3] % m) % m; printf("%d\n" , ans); return 0; }