CodeForces - 55D Beautiful numbers (数位DP)

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

11 9

Output

9

Input

112 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\n",solve(r)-solve(l-1));
    }
    return 0;
}


原文地址:https://www.cnblogs.com/a249189046/p/9688910.html

时间: 2024-10-14 19:17:37

CodeForces - 55D Beautiful numbers (数位DP)的相关文章

CodeForces 55D Beautiful numbers 数位DP+数学

题意大概是,判断一个正整数区间内有多少个整数能被它自身的每一个非零的数字整除. 因为每一个位置上的整数集s = {0,1,2,3,4,5,6,7,8,9} lcm(s) = 2520 现在有一个整数t是由s中一个或者多个数字构成的,记为abcde,显然t = a*10^4+b*10^3+c*10^2+d*10^1+e 要使得t能被a,b,c,d,e整除,必然有t % lcm(a,b,c,d,e) = 0 因为a,b,c,d,e去重之后一定是s的一个子集,所以lcm(s)一定是lcm(a,b,c,

CodeForces 55D Beautiful numbers(数位dp&amp;&amp;离散化)

题目链接:[kuangbin带你飞]专题十五 数位DP A - Beautiful numbers 题意 ps:第一道数位dp,题真好,虽然是参考大牛方法悟过才a,但仍收获不少. 求一个区间内的Beautiful numbers有多少个.Beautiful numbers指:一个数能整除所有组成它的非0数字. 例如15可以被1和5整除,所以15是Beautiful numbers. 思路 Beautiful numbers指:一个数能整除所有组成它的非0数字. 等同于 一个数能整除 所有组成它的

CodeForces 55D - Beautiful numbers - [数位DP+离散化]

题目链接:https://cn.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

CodeForces - 55D - Beautiful numbers(数位DP,离散化)

链接: 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

CodeForces 55D Beautiful numbers (数位DP)

题意:给求给定区间中该数能整除每一位的数的数量. 析:dp[i][j][k] 表示前 i 位,取模2520为 j,最小倍数是 k,但是这样,数组开不下啊,那怎么办呢,其实,0-9的最小公倍数的不同各类并没有那么多, 其实就48种,所以我们可以给这48个一个编号,然后就能开出来了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <strin

Codeforces 55D Beautiful numbers 数位dp(入门

题目链接:点击打开链接 题意: 我们认为一个数 num 能被每一位上的数字整除(expect 0) 那么这个数num就是合法的. 给出区间[l,r] ,问这个区间内有多少个合法的数. 首先solve(long x) 返回 [0, x] 内的合法个数,答案就是 solve(r) - solve(l-1); 以1234567为例 flag表示当前这位是能任意填,还是只能填<=该位对应的数字 若当前搜索的是第三位,且第二位已经填了0或1,则此时第三位可以任意填. 若第二位填的是2,则第三位只能填 [0

FZU2179/Codeforces 55D beautiful number 数位DP

题目大意: 求  1(m)到n直接有多少个数字x满足 x可以整出这个数字的每一位上的数字 思路: 整除每一位.只需要整除每一位的lcm即可 但是数字太大,dp状态怎么表示呢 发现 1~9的LCM 是2520 ....也就是说只要对这个数mod2520 剩下的余数能整除lcm就可以整除了.. 计数的时候还有一个技巧,具体见注释 此外这个题还卡常数了,预处理lcm才过了.. 代码如下: #include <iostream> #include <stdio.h> #include<

Codeforces 55D. Beautiful numbers(数位DP,离散化)

Codeforces 55D. Beautiful numbers 题意 求[L,R]区间内有多少个数满足:该数能被其每一位数字都整除(如12,24,15等). 思路 一开始以为是数位DP的水题,觉得只需要记录搜到当前位出现了哪些数字作为状态即可,明显是假算法...感觉这是一道数位DP好题.可以这样思考:一个数要想被其各位数字分别都整除,等价于它被那些数字的LCM整除.因此记录当前位,当前数对(1~9的LCM)取模的结果,当前出现的数字的LCM这三个值作为状态才合理,即dp[pos][sum][

codeforces 55D D. Beautiful numbers(数位dp+数论)

题目链接: codeforces 55D 题目大意: 求在[l,r]中能够整除自己每个数位上的数字的数的个数. 题目分析: 首先我们能够知道如果这个数能够整除它的每个数位上的数字,那么它一定能够整除他们的最小公倍数,是充要的. 那么我们定义状态dp[i][j][k]代表i位在任意组合下得到的所有数位的数字的最小公倍数为j的每个数位上的数字之积%2520为k的方案数. 我们可以知道所有的公倍数最大不会超过2520,而且他们都是2520的约数,所以如果他们能够整除2520的余数,那么证明他们能够整除