• CodeForces


    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.


    Input

    The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two natural numbers li and ri (1 ≤ li ≤ ri ≤ 9 ·1018).

    Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cin (also you may use %I64d).

    Output

    Output should contain t numbers — answers to the queries, one number per line — quantities of beautiful numbers in given intervals (from li to ri, inclusively).

    Examples
    Input
    1
    1 9
    Output
    9
    Input
    1
    12 15
    Output
    2

    题意:求[l,r]中,满足能够整除自身各个数位的数的个数有多少
    分析:要在这么大的范围中,求出数的个数,我们能够想到用数位DP,但是使用数位DP,需要找到当扫描到数的第num位的时候,能够满足的某些共性,得到相同的值。这样作为DP基础。
    题目要求的是能够整除各个数位,但是我们不可能将每个数位用DP维度表现出现。通过数论知识,我们可以知道,如果一个数,整除一些数,那么它一定能整除这些的数的最小公倍数,
    所以整除最小公倍数是一个充要条件。这个时候,最后判断是用得到的数,看是否能除尽所有数位的最小公倍数,所以当我们扫描到第num位的时候,需要知道是前面已经扫描过的所有数位的最小公倍数是多少,以及这些数表示的值是多少,由于这些数表示的值
    会很大,所以我们需要取模,将它与所有数位的公倍数取模是不影响的,然后2520是1,2,3,4,5,6,7,8,9的公倍数,所以模上2520即可。
    另外还要注意的是,因为内存的限制,在开DP维度的时候,必要要用到的是2520*20,所以用来储存所有数位的最小公倍数的位置,不能开到2520,因为是最小公倍数,实际上1-2520的很多位置是不需要用到的
    所以可以直接将这些数离散化处理,再进行DP
    代码如下:
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    vector<int>V;
    int get_id(int x)
    {
        return lower_bound(V.begin(),V.end(),x)-V.begin()+1;
    }
    LL a[50];
    LL dp[20][50][2550];
    LL dfs(int num,LL id,bool limit,int now)
    {
        if(num==-1)
        {
          if(now%V[id-1]==0)
          return 1;
          else
          return 0;
        }
        if(!limit&&dp[num][id][now]!=-1)
        return dp[num][id][now];
    
        int up=limit?a[num]:9;
        LL ans=0;
        for(LL i=0;i<=up;i++)
        {
          LL lcm=V[id-1];
          if(i==0)
          ans+=dfs(num-1,get_id(lcm),limit&&i==up,(now*10+i)%2520);
          else
          ans+=dfs(num-1,get_id(lcm*i/__gcd(lcm,i)),limit&&i==up,(now*10+i)%2520);
        }
    
       if(!limit)
       dp[num][id][now]=ans;
       return ans;
    }
    
    void init_dfs(LL pos,LL now)
    {
        V.push_back(now);
        if(pos==10)
        return;
        for(LL i=pos;i<=9;i++)
        init_dfs(i+1,now*i/__gcd(i,now));
    }
    LL solve(LL x)
    {
      int cnt=0;
      while(x>0)
      {
         a[cnt]=x%10;
         cnt++;
         x/=10;
      }
      return dfs(cnt-1,get_id(1),1,0);
    }
    LL t,l,r;
    int main()
    {
        init_dfs(2,1);
        sort(V.begin(),V.end());
        V.erase(unique(V.begin(),V.end()),V.end());
        scanf("%lld",&t);
        memset(dp,-1,sizeof(dp));
        while(t--)
        {
          scanf("%lld%lld",&l,&r);
          printf("%lld
    ",solve(r)-solve(l-1));
        }
        return 0;
    }



  • 相关阅读:
    HDU-2067-小兔的棋盘
    HDU-1861-游船出租
    C语言笔记
    P1164 小A点菜
    P1028 数的计算
    P1217 [USACO1.5]回文质数 Prime Palindromes
    P1088 火星人
    P2392 kkksc03考前临时抱佛脚
    P3799 妖梦拼木棒
    First Step (ファーストステップ)
  • 原文地址:https://www.cnblogs.com/a249189046/p/9688910.html
Copyright © 2020-2023  润新知