zoukankan      html  css  js  c++  java
  • CF 55 D. Beautiful numbers

    D. Beautiful numbers

    链接

    题意:

      求[L,R]中多少个数字可以整除它们的每一位上的数字。

    分析:

      要求模一些数字等于0等价于模它们的lcm等于0,所以可以记录当前出现的数字的lcm,最后判断组成的数字是否模lcm等于0。

      但是这个数字太大记录不下。根据一个性质a%b=(a%kb)%b,所以可以记录当前的数字模2520的值,最后模一下lcm。

      这样的状态是$20 imes 2520 imes 2520$的,状态太大了,考虑如何缩小空间。因为1~9的lcm只能是50个左右,所以可以将第三维压成50。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline LL read() {
        LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 2520;
    LL dp[30][50][N + 10];
    int num[50]={0,1,2,3,4,5,6,7,8,9,10,12,14,15,18,20,21,24,28,30,35,36,40,42,45,56,60,63,70,72,84,90,105,120,126,140,168,180,210,252,280,315,360,420,504,630,840,1260,2520};
    int a[30], pos[N + 10];
    
    int gcd(int a,int b) { return b == 0 ? a : gcd(b, a % b); }
    int getlcm(int a,int b) { return a * b / gcd(a, b); }
    
    LL dfs(int p,int lcm,int now,bool lim) {
        if (p == 0) return lcm && now % num[lcm] == 0;
        if (!lim && ~dp[p][lcm][now]) return dp[p][lcm][now];
        int u = lim ? a[p] : 9;
        LL ans = 0;
        for (int i = 0; i <= u; ++i) {
            int t = lcm ? pos[getlcm(num[lcm], max(i, 1))] : i;
            ans += dfs(p - 1, t, (now * 10 + i) % N, lim && i == u);
        }
        if (!lim) dp[p][lcm][now] = ans;
        return ans;    
    }
    LL solve(LL x) {
        if (x <= 0) return 0;
        int pos = 0;
        while (x) {
            a[++pos] = x % 10; x /= 10;
        }
        return dfs(pos, 0, 0, 1);
    }
    int main() {
        memset(dp, -1, sizeof(dp));
        for (int i = 0; i < 49; ++i) pos[num[i]] = i;
        for (int T = read(); T --; ) {
            LL x = read(), y = read();
            cout << (solve(y) - solve(x - 1)) << "
    ";
        }
        return 0;
    }
  • 相关阅读:
    【Oracle 故障处理一则】 ORA-600
    【转载】关于物化视图
    【转载】OTLP和OLAP的区别
    【转载】Linux追加虚拟内存Swap
    【转载】Keepalived 的使用
    【识记】修复oracle的坏块
    K-means算法[聚类算法]
    决策树ID3算法[分类算法]
    6)图[1]之邻接矩阵存储[深度遍历和广度遍历]
    2)杨辉三角[2]递归实现
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10549137.html
Copyright © 2011-2022 走看看