zoukankan      html  css  js  c++  java
  • CodeForces

    链接:

    https://vjudge.net/problem/CodeForces-55D

    题意:

    Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with this and just count the quantity of beautiful numbers in given ranges.

    思路:

    数位DP,但是数的范围太大不能直接记录,先优化。
    我们有可以推出(sum \% (n*x) \% x = sum \% x)
    证明如下:
    (sum = k*x+b)
    ((k * x+b)\% (n * x) \% x)
    (k = k_a*n+k_b)
    (((k_a*n+k_b)*x+b) \% (n*x) \% x)
    ((k_a*n*x+k_b*x+b) \% (n*x) \% x)
    ((k_b*x+b) \% x)
    (b = (k*x+b) \% x = b)
    所以我们可以把值先模nx,取nx = 2520(1~9的lcm),
    令Dp(i, j, k),表示i位置,模 n*x为j,k等于各位的lcm,(因为n%每个数都为0 = n%lcm = 0)
    考虑lcm的个数,如果用2520来记录会爆内存,考虑lcm的值,每次都是两个数相乘/gcd,同时每个最多为9,则每个lcm都是2520的约数,枚举约数离散化。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int MOD = 1e9+7;
    const int MAXN = 1e6+10;
    
    LL Dp[30][2600][50];
    int Hash[2600];
    int dig[30];
    
    LL Gcd(LL a, LL b)
    {
        if (b == 0)
            return a;
        return Gcd(b, a%b);
    }
    
    LL Dfs(int pos, LL num, int lcm, bool lim)
    {
        if (pos == -1)
            return num%lcm == 0;
        if (!lim && Dp[pos][num][Hash[lcm]] != -1)
            return Dp[pos][num][Hash[lcm]];
        int up = lim ? dig[pos] : 9;
        LL cnt = 0;
        for (int i = 0;i <= up;i++)
            cnt += Dfs(pos-1, (num*10+i)%2520, i ? lcm*i/Gcd(lcm, i) : lcm, lim && i == up);
        if (!lim)
            Dp[pos][num][Hash[lcm]] = cnt;
        return cnt;
    }
    
    LL Solve(LL x)
    {
        int p = 0;
        while(x)
        {
            dig[p++] = x%10;
            x /= 10;
        }
        return Dfs(p-1, 0, 1, true);
    }
    
    int main()
    {
        // freopen("test.in", "r", stdin);
        int cnt = 0;
        for (int i = 1;i <= 2520;i++)
        {
            if (2520%i == 0)
                Hash[i] = ++cnt;
        }
        memset(Dp, -1, sizeof(Dp));
        int t;
        scanf("%d", &t);
        while(t--)
        {
            LL a, b;
            scanf("%I64d %I64d", &a, &b);
            printf("%I64d
    ", Solve(b)-Solve(a-1));
        }
    
        return 0;
    }
    
  • 相关阅读:
    7.3---直线是否相交(CC150)
    7.2---蚂蚁相遇问题(CC150)
    5.6---交换整数的奇数位和偶数位(CC150)
    5.5---整数A转成整数B(CC150)
    5.2---小数的二进制表示(CC150)
    5.1---二进制数插入(CC150)
    4.6---找二叉树中序后继(CC150)
    4.5---判断是否是二叉排序树BST(CC150)
    4.4---建立二叉树的链表
    linux中查看java进程
  • 原文地址:https://www.cnblogs.com/YDDDD/p/11992755.html
Copyright © 2011-2022 走看看