题目大意:问长度为$n$的$Sam$数有几个,$Sam$数的定义为没有前导零,相邻两个数字之差绝对值小于等于$2$的数
题解:发现转移方程一定,可以矩阵快速幂。
卡点:没有特判$n=1$的情况
C++ Code:
#include <cstdio> const int mod = 1e9 + 7; inline int abs(int a) {return a < 0 ? -a : a;} inline void up(int &a, int b) {a += b - mod; a += a >> 31 & mod;} struct matrix { #define M 10 int s[M][M]; inline void E() { for (int i = 0; i < M; i++) s[i][i] = 1; } inline void init() { for (int i = 0; i < M; i++) { for (int j = 0; j < M; j++) s[i][j] = abs(i - j) <= 2; } } inline friend matrix operator * (const matrix &lhs, const matrix &rhs) { matrix res; long long ans; for (int i = 0; i < M; i++) { for (int j = 0; j < M; j++) { ans = 0; for (int k = 0; k < M; k++) ans += static_cast<long long> (lhs.s[i][k]) * rhs.s[k][j]; res.s[i][j] = ans % mod; } } return res; } #undef M } ans, base; long long n; int main() { scanf("%lld", &n); if (n == 1) { puts("10"); return 0; } base.init(); for (int i = 1; i < 10; i++) ans.s[0][i] = 1; for (n--; n; n >>= 1, base = base * base) if (n & 1) ans = ans * base; int res = 0; for (int i = 0; i < 10; i++) up(res, ans.s[0][i]); printf("%d ", res); return 0; }