• 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;
    }
  • 相关阅读:
    各个版本中Notification对象创建的方法
    数据结构一:线性表
    安装eclipse中文汉化包后无法打开eclipse【转】
    在MFC里面使用自定义的OpenGL类进行绘图(基于VS2010)
    2016-2-25 我的博客开通了
    从C#到Swift原来这么简单,So Easy!
    CocoaPods安装及使用(包含重装步骤)
    Xcode键盘快捷键
    参考资料收集
    重温算法和数据结构:二分查找
  • 原文地址:https://www.cnblogs.com/sagitta/p/4985429.html
Copyright © 2020-2023  润新知