zoukankan      html  css  js  c++  java
  • hdu 5564 Clarke and digits

    题目链接

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

    -----------------------------------------------------------------------------------------

    刚读完题目感觉像是数位DP,然而仔细看了数据范围后感觉很不可做。

    与数位DP题目对比可以发现 此题数据范围要大一些,却没有对每一位进行限制

    于是便可以愉快地进行矩阵乘法优化DP啦

    如果矩阵构造(将递推式转换为矩阵形式)还不熟练的话 可以参考

    挑战程序设计竞赛(第2版) 3.4.2节

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int mod = 1e9 + 7, L = 70 + 1;
    int t, l, r, m;
    long long raw[L][L], tmp[L][L], a[L][L], b[L][L], f[L];
    long long ans1, ans2;
    void mul(long long A[L][L], long long B[L][L])
    {
        memset(tmp, 0, sizeof tmp);
        for(int i = 0; i < L; ++i)
            for(int j = 0; j < L; ++j)
            {
                for(int k = 0; k < L; ++k)
                    tmp[i][j] += A[i][k] * B[k][j] % mod;
                tmp[i][j] %= mod;
            }
        for(int i = 0; i < L; ++i)
            for(int j = 0; j < L; ++j)
                A[i][j] = tmp[i][j];
    }
    long long solve(int lim)
    {
        if(!lim)
            return 0;
        if(lim == 1)
            return 1;
        lim -= 2;
        for(int i = 0; i < L; ++i)
            for(int j = 0; j < L; ++j)
                a[i][j] = b[i][j] = raw[i][j];
        while(lim)
        {
            if(lim & 1)
                mul(a, b);
            mul(b, b);
            lim >>= 1;
        }
        long long tans = 0;
        for(int i = 0; i < L; ++i)
            tans += a[70][i] * f[i] % mod;
        return tans % mod;
    }
    int main()
    {
        for(int i = 1; i <= 9; ++i)
            f[i * 7 + i % 7] = 1;
        f[70] = 1;
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d%d%d", &l, &r, &m);
            memset(raw, 0, sizeof raw);
            for(int i = 0; i <= 9; ++i)
                for(int j = 0; j <= 9; ++j)
                    if(i + j != m)
                    {
                        for(int k = 0; k < 7; ++k)
                        {
                            raw[i * 7 + (k * 10 + i) % 7][j * 7 + k] = 1;
                            if((k * 10 + i) % 7 == 0)
                                ++raw[70][j * 7 + k];
                        }
                    }
            raw[70][70] = 1;
            ans1 = solve(l - 1);
            ans2 = solve(r);
            printf("%lld
    ", (ans2 - ans1 + mod) % mod);
        }
        return 0;
    }
  • 相关阅读:
    bash while until 循环用法
    微信小程序入门介绍
    jquery遍历
    jquery获取元素和DOM获取元素
    ul在div中水平居中效果
    一个文字在一个图片上水平居中,并且悬浮变大特效
    一个div在另一个div中垂直居中的方法
    layer插件的使用
    百度分享插件使用
    图标字体
  • 原文地址:https://www.cnblogs.com/sagitta/p/4985429.html
Copyright © 2011-2022 走看看