http://codeforces.com/problemset/problem/55/D
/**
CF 55D 数位dp(一个数是组成它的所有位数对应数的倍数)
题目大意:找出给定区间内有多少数,其本身是所有组成它的各个位上的数的倍数
解题思路:(kuangbin)一个数能被它的所有非零数位整除,则能被它们的最小公倍数整除,而1到9的最小公倍数为2520,
数位DP时我们只需保存前面那些位的最小公倍数就可进行状态转移,到边界时就把所有位的lcm求出了,
为了判断这个数能否被它的所有数位整除,我们还需要这个数的值,显然要记录值是不可能的,其实我们只
需记录它对2520的模即可,这样我们就可以设计出如下数位DP:dfs(pos,mod,lcm,f),pos为当前
位,mod为前面那些位对2520的模,lcm为前面那些数位的最小公倍数,f标记前面那些位是否达到上限,
这样一来dp数组就要开到19*2520*2520,明显超内存了,考虑到最小公倍数是离散的,1-2520中可能
是最小公倍数的其实只有48个,经过离散化处理后,dp数组的最后一维可以降到48,这样就不会超了。
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int mod=2520;
typedef long long LL;
LL dp[25][mod][50];
int index[2530],bit[25];
int gcd(int a,int b)
{
if(b==0)return a;
else return gcd(b,a%b);
}
int lcm(int a,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++;
}
}
LL 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]];
LL ans=0;
int end=flag?bit[pos]:9;
for(int i=0; i<=end; i++)
{
int nowsum=(presum*10+i)%mod;
int nowlcm=prelcm;
if(i)nowlcm=lcm(nowlcm,i);
ans+=dfs(pos-1,nowsum,nowlcm,flag&&i==end);
}
if(!flag)dp[pos][presum][index[prelcm]]=ans;
return ans;
}
LL solve(LL x)
{
int len=0;
while(x)
{
bit[len++]=x%10;
x/=10;
}
return dfs(len-1,0,1,1);
}
int main()
{
int T;
init();
memset(dp,-1,sizeof(dp));
scanf("%d",&T);
while(T--)
{
LL r,l;
scanf("%I64d%I64d",&l,&r);
printf("%I64d\n",solve(r)-solve(l-1));
}
return 0;
}