[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 }

 

posted @ 2017-08-21 14:22  Kirai  阅读(264)  评论(0编辑  收藏  举报