找[l,r]区间中,能被自己各个非零数位整除的数的个数。

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
一看就是满足区间减法。现在就讨论怎么求就行了。
首先lcm(1..9)=2520, int MOD=2520;保存每一个数是不现实的,所以我们就.保存x%MOD就行了。
preSum表示已经讨论的前面的几个数位的值(前串),preLcm表示前穿的Lcm。
这里注意到1...9的各种lcm可以离散化处理,只有48个,这样可以大大减少数组的空间。
我们再用flag来表示当前位的数字大小是否超过x对应位的大小
例:x=15666;当我们讨论到千位是1,2,3,4时,后面三位是随便选的,讨论千位是5是,百位就不能随便选了,要<=6,此时在千位我们就达到了边界。

代码:

#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=25;
const int MOD=2520;
long long dp[MAXN][MOD][48];
int index[MOD+10],bit[MAXN];
long long int gcd (long long int a,long long int b) {return (b==0)?a:gcd(b,a%b);}
long long int lcm (long long int a,long long int b){return a/gcd(a,b)*b;}
void init()
{
    int num=0;
    for (int i=1;i<=MOD;++i)
    if (MOD%i==0)
    index[i]=num++;//   把2520的所有因子进行编号,第一个因子编号1..........
}
long long dfs (int pos,int preSum,int preLcm,bool flag)
{
    if (pos==-1)
    return preSum%preLcm==0;
    if (!flag && dp[pos][preSum][index[preLcm]]!=-1)
    return dp[pos][preSum][index[preLcm]];
    long long ans=0;
    int endd=flag?bit[pos]:9;
    for (int i=0;i<=endd;i++)
    {
        int nowSum=(preSum*10+i)%MOD;
        int nowLcm=preLcm;
        if (i)
        nowLcm=lcm(nowLcm,i);
        ans+=dfs(pos-1,nowSum,nowLcm,flag&&i==endd);
    }
    if (!flag)
    dp[pos][preSum][index[preLcm]]=ans;
    return ans;
}
long long calc (long long x)
{
    memset(bit,0,sizeof bit);
    int pos=0;
    while (x)
    {
        bit[pos++]=x%10;
        x/=10;
    }
    return dfs(pos-1,0,1,1);
}
int main()
{
    int t;
    long long int l,r;
    memset(dp,-1,sizeof dp);
   cin>>t;
    init();
    while (t--)
    {
        cin>>l>>r;
       cout<<calc(r)-calc(l-1)<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据题意,我们需要到[1,M]范围内所有能被2520整除个数。由于M非常大,我们无法直接枚举每个数,因此需要寻一种更高效的方法。 首先,我们可以将2520分解质因,得到2520 = 2^3 * 3^2 * 5 * 7。由于2520是所有能被1至10的每个数整除的最小正整,因此任何一个能被2520整除,一定也能被1至10的每个数整除。 我们可以利用这个特性来简化问题。具体来说,我们可以枚举1至10的每个数,分别计算出[1,M]范围内能被该整除个数,然后将它们相乘即可得到最终的答案。 对于1至10的每个数,我们可以用的知识来计算出能被它整除个数。以7为例,假设M=1000000000000,我们需要计算出[1,M]范围内能被7整除个数。首先,我们可以到最大的小于等于M的7的倍,即M' = 999999999993。然后,我们可以将[1,M']范围内的所有都除以7,得到一个新的区间[1,N'],其N' = M' / 7 = 142857142856。这个区间的所有都是7的倍,因此它们中有N'个数能被7整除。但是,我们还需要考虑一些特殊情况,比如7*7、7*7*7等等。这些在[1,M]范围内也能被7整除,因此需要将它们的贡献加上去。具体来说,能被7整除,有N'个数同时能被7和7整除,有N'/7个数同时能被7、7和7整除,以此类推。因此,我们可以得到计算公式: count_7 = N' + N'/7 + N'/7^2 + ... = N' * (1 - 1/7) = 122448979591 同理,我们可以计算出1至10个数的贡献,然后将它们相乘即可得到最终的答案。代码如下: ```python M = 1000000000000 def count_divisible(n): m = (M // n) * n if m == 0: return 0 else: k = m // n return k + count_divisible(n * 2) - count_divisible(n * 3) + count_special(n, k) def count_special(n, k): if n == 2 or n == 5: return 0 elif n == 3: return k // 3 elif n == 7: return k // 7 + count_special(49, k) elif n == 49: return k // 49 + count_special(343, k) elif n == 343: return k // 343 result = count_divisible(1) * count_divisible(2) * count_divisible(3) * count_divisible(5) * count_divisible(7) print(result) ``` 运行时间大约为2秒,可以通过本题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值