真是好数啊:)
#include<iostream>
#include<cstring>
using namespace std;
using ll=long long;
ll dp[20][11];
//预处理出两数间是否符合倍数关系
int flag[11][11];
int g[20];
void init(){
for(int i=0;i<10;++i){
dp[1][i]=1;
}
for(int i=2;i<=19;++i){
for(int j=0;j<10;++j){//首位0还是需要的,因为后面的dp需要它
for(int k=0;k<10;++k){
if(flag[j][k]==1)//成倍数关系,才累加
dp[i][j]+=dp[i-1][k];
}
}
}
}
ll solve(ll n){
int len=0;
ll ans=0;
memset(g,0,sizeof(g));
while(n){
g[++len]=n%10;
n/=10;
}
for(int i=1;i<=len-1;++i){
for(int j=1;j<=9;++j){
ans+=dp[i][j];
}
}
for(int i=1;i<g[len];i++){
ans+=dp[len][i];
}
for(int i=len-1;i>0;--i){
for(int j=0;j<g[i];++j){
if(flag[g[i+1]][j]==1){//高位与当前位满足倍数关系
ans+=dp[i][j];
}
}
if(flag[g[i+1]][g[i]]==0)//当前位已经不满足了,及时退出
break;//这一步是必要的!!因为我这个循环只考虑当前位与上一位是否符合
}
return ans;
}
int main(){
int n;
cin>>n;
ll l,r;
for(int i=0;i<10;++i){
for(int j=0;j<10;++j){
if(i==0||j==0||i%j==0||j%i==0){
flag[i][j]=1;
}
}
}
init();
while(n--){
cin>>l>>r;
ll ans=solve(r+1)-solve(l);
if(l==0)
cout<<ans+1<<endl;
else
cout<<ans<<endl;
}
}