题解
不可以发现,只有\(\le 3\)位数才会出现非3友好的情况。证明:如果前\(i\)个数模\(3=\)前\(i+1\)个数模\(3\),则说明第\(i+1\)个数可以被\(3\)整除。因此非3友好数的所有前缀模\(3\)一定不相等,根据鸽巢原理可得上述结论。
打表即可,以下代码为TLE的数位dp修改而来(。﹏。*)
AC代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[20],b[20][1050],c[20],n;
int dfs(int pos,bool ok,int sta,bool lim,bool zr)
{
if(!pos) return ok;
if(!lim && !zr && (!ok && b[pos][sta]!=-1)) return b[pos][sta];
if(!lim && !zr && (ok && c[pos]!=-1)) return c[pos];
int up=lim?a[pos]:9,ans=0,tmp;
if(ok)
{
for(int i=0;i<=up;i++) ans+=dfs(pos-1,ok,sta,lim && i==up,zr && !i);
if(!lim && !zr) c[pos]=ans;
return ans;
}
bool num[11];
memset(num,0,sizeof(num));
int qwq=sta;
for(int i=0;sta;i++) num[i]=(sta&1),sta>>=1;
num[0]=num[3]=num[6]=num[9]=1;
for(int i=0;i<=up;i++)
{
if(num[i] && (!zr || i)) ans+=dfs(pos-1,1,sta,lim && i==up,zr && !i);
else
{
tmp=0;
for(int j=i+1;j<=9;j++)
if(num[j]) tmp|=(1<<(j-i));
for(int j=3;j<=18;j+=3)
if(j>i && j-i<=9) tmp|=(1<<(j-i));
if(i%3==0) tmp|=1;
ans+=dfs(pos-1,ok,tmp,lim && i==up,zr && !i);
}
}
if(!lim && !zr) b[pos][sta]=ans;
return ans;
}
int sol(int x)
{
n=0;
while(x) {a[++n]=x%10; x/=10;}
int tmp=(1<<3)+(1<<6)+(1<<9)+1;
return dfs(n,0,tmp,1,1);
}
signed main()
{
memset(b,-1,sizeof(b));
memset(c,-1,sizeof(c));
int t,l,r,ans;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld",&l,&r); ans=0;
if(l<100) ans=sol(min(100ll,r))-sol(l-1);
else ans=1;
printf("%lld\n",ans+max(0ll,r-max(100ll,l)));
}
return 0;
}