• HDU 5564 Clarke and digits 状压dp+矩阵加速


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5564

    题意:

    求长度在[L,R]范围,并且能整除7的整数的总数。

    题解:

    考虑最原始的想法:

    dp[i][j][k]表示长度为i,并且对7取模得到j的以k结尾的数。

    则有状态转移方程dp[i+1][(h*10)+l)%7][k]+=dp[i][h][k'](k+k'!=K).

    但是i范围是1~10^9,需要矩阵加速。

    这里对dp[i][j][k]的[j][k]两个状态进行压缩,得到转移矩阵mat[70][70],其中mat[s1][s2]表示由状态s2变到状态s1的可行性。

    并且由于dp[i][j][k]记录的是长度为i的情况,而我们要求的是所有长度小于等于i的前缀和,所以,我们还要加一行一列来计算所有模7等于零的数的个数。

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 
     6 const int maxn = 71;
     7 const int mod = 1e9 + 7;
     8 typedef long long LL;
     9 
    10 struct Matrix {
    11     LL mat[maxn][maxn];
    12     Matrix() { memset(mat, 0, sizeof(mat)); }
    13     friend Matrix operator *(const Matrix& A, const Matrix& B);
    14     friend Matrix operator ^(Matrix A, int n);
    15 };
    16 
    17 Matrix operator *(const Matrix& A, const Matrix& B) {
    18     Matrix ret;
    19     for (int i = 0; i < maxn; i++) {
    20         for (int j = 0; j < maxn; j++) {
    21             for (int k = 0; k < maxn; k++) {
    22                 ret.mat[i][j] += A.mat[i][k] * B.mat[k][j] % mod;
    23                 ret.mat[i][j] %= mod;
    24             }
    25         }
    26     }
    27     return ret;
    28 }
    29 
    30 Matrix operator ^(Matrix A, int n) {
    31     Matrix ret;
    32     for (int i = 0; i < maxn; i++) ret.mat[i][i] = 1;
    33     while (n) {
    34         if (n & 1) ret = ret*A;
    35         A = A*A;
    36         n /= 2;
    37     }
    38     return ret;
    39 }
    40 
    41 int L, R, K;
    42 
    43 int main() {
    44     int tc;
    45     scanf("%d", &tc);
    46     while (tc--) {
    47         scanf("%d%d%d", &L, &R, &K); L--;
    48         Matrix A, B;
    49         //转移矩阵 
    50         for (int i = 0; i < 70; i++) {
    51             for (int j = 0; j < 70; j++) {
    52                 int x1 = i / 10, y1 = i % 10;
    53                 int x2 = j / 10, y2 = j % 10;
    54                 if (y1 + y2 == K) continue;
    55                 if ((x2*10 + y1) % 7 == x1) A.mat[i][j] = 1;
    56             }
    57         }
    58         //计算前缀和 
    59         for (int i = 0; i < 10; i++) A.mat[70][i] = 1;
    60         A.mat[70][70] = 1;
    61         
    62         //初始向量 
    63         for (int i = 1; i < 10; i++) B.mat[(i%7)*10+i][0]++;
    64         
    65         Matrix AR = A^R, AL = A^L;
    66         Matrix BR = AR*B, BL = AL*B;
    67         LL ans = BR.mat[70][0] - BL.mat[70][0];
    68         printf("%lld
    ", (ans%mod+mod)%mod);
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    Docker 制作定制asp.netcore 的容器
    Windows docker k8s asp.net core
    Ubuntu 18 Kubernetes集群的安装和部署 以及Helm的安装
    ubuntu 18 docker 搭建Prometheus+Grafana
    ubuntn18 docker zabbix+grafana安装和使用
    .net Core MongoDB用法演示
    Ubuntu18 安装搭建Harbor
    ubuntu docker inflxudb(安装 使用 备份 还原 以及python编码) telegraf Grafana
    python selenium爬虫工具
    python selenium IE Firxfor pyinstaller
  • 原文地址:https://www.cnblogs.com/fenice/p/5510013.html
Copyright © 2020-2023  润新知