二次联通门 : BZOJ 2326: [HNOI2011]数学作业
/* BZOJ 2326: [HNOI2011]数学作业 此题的递推式很显然。。。 f(n) = len (n) * 10 * f (n - 1) + n; 变为矩阵则为 f(n) len(n)*10 1 1 f(n-1) n = 0 1 1 * n-1 1 0 1 1 1 那么就矩乘搞一搞就好 对于len(n)每次则每次分开乘进去就行 */ #include <cstdio> #include <cstring> void read (long long &now) { register char word = getchar (); for (now = 0; word < '0' || word > '9'; word = getchar ()); for (; word >= '0' && word <= '9'; now = now * 10 + word - '0', word = getchar ()); } long long N; long long Mod; struct Martix { static const int _L = 3; long long data[_L][_L]; inline void Fill () { memset (this->data, 0, sizeof this->data); this->data[1][0] = this->data[2][0] = 1; this->data[1][1] = this->data[2][1] = 1; this->data[2][2] = 1; } Martix operator * (const Martix &now) const { Martix res; for (register int i = 0, j, k; i < _L; i ++) for (j = 0; j < _L; j ++) { res.data[i][j] = 0; for (k = 0; k < _L; k ++) res.data[i][j] = (res.data[i][j] + this->data[i][k] * now.data[k][j]) % Mod; } return res; } }; Martix operator ^ (Martix now, long long P) { Martix res; for (register int i = 0, j; i < Martix :: _L; i ++) for (j = 0; j < Martix :: _L; j ++) res.data[i][j] = (i == j); for (; P; P >>= 1) { if (P & 1) res = res * now; now = now * now; } return res; } Martix Answer; inline void Solve (long long t, long long P) { Martix res; res.Fill (); res.data[0][0] = t % Mod; Answer = Answer * (res ^ (P - t / 10 + 1)); } int main (int argc, char *argv[]) { read (N); read (Mod); for (int i = 0; i < Martix :: _L; i ++) Answer.data[i][i] = 1; long long T = 10; for (; N >= T; Solve (T, T - 1), T *= 10); Solve (T, N); printf ("%lld", Answer.data[2][0]); return 0; }