[HIHO1560] H国的身份证号码II(dp,计数,矩阵快速幂)
题目链接:http://hihocoder.com/problemset/problem/1560
有了数位dp的思维基础,这个递推式很容易想到:
构造转移矩阵的时候思考数位dp的转移。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const LL mod = 1e9+7; 6 const int maxn = 11; 7 8 typedef struct Matrix { 9 LL m[maxn][maxn]; 10 int r, c; 11 Matrix(){ 12 r = c = 0; 13 memset(m, 0, sizeof(m)); 14 } 15 } Matrix; 16 Matrix mul(Matrix m1, Matrix m2, LL mod) { 17 Matrix ans = Matrix(); 18 ans.r = m1.r; ans.c = m2.c; 19 for(int i = 0; i < m1.r; i++) { 20 for(int j = 0; j < m2.r; j++) { 21 for(int k = 0; k < m2.c; k++) { 22 if(m2.m[j][k] == 0) continue; 23 ans.m[i][k] = (ans.m[i][k] + (m1.m[i][j] * m2.m[j][k]) % mod) % mod; 24 } 25 } 26 } 27 return ans; 28 } 29 Matrix quickmul(Matrix m, LL n, LL mod) { 30 Matrix ans = Matrix(); 31 for(int i = 0; i < m.r; i++) ans.m[i][i] = 1; 32 ans.r = m.r; 33 ans.c = m.c; 34 while(n) { 35 if(n & 1) ans = mul(m, ans, mod); 36 m = mul(m, m, mod); 37 n >>= 1; 38 } 39 return ans; 40 } 41 42 LL n; 43 int k; 44 45 signed main() { 46 // freopen("in", "r", stdin); 47 while(~scanf("%lld%d",&n,&k)) { 48 Matrix p; p.r = p.c = 10; 49 for(int i = 0; i <= min(k, 9); i++) { 50 for(int j = 0; j <= min(k, 9); j++) { 51 if(i * j <= k) p.m[i][j] = 1; 52 } 53 } 54 p = quickmul(p, n-1LL, mod); 55 LL ret = 0; 56 for(int i = 0; i <= min(k, 9); i++) { 57 for(int j = 1; j <= min(k, 9); j++) { 58 ret += p.m[i][j]; 59 ret %= mod; 60 } 61 } 62 printf("%lld\n", ret); 63 } 64 return 0; 65 }