题意
L,R<=10^18,T<=20
分析
通过打表我们不难发现d(n)就等于n%9.我们考虑如何查询[1,R]之间的好数。
枚举d(x),若有d(x)*x<=R,则有x<=R/d(x),且x同时要满足x%9==d(x)。那么满足条件的x数量就等于R/d(x)/9.若R/d(x)%9>=d(x)则还要+1.
但我们不难注意到这还有一个数被重复统计的情况。例如36既可以表示成6*d(6)也可以表示成12*d(12)。那么我们只要容斥掉这些情况就好了。
有大爷打表发现了答案其实是有周期性的,周期大概是两万多,那么就只要预处理前两万多的答案就可以O(1)询问了。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
LL solve(LL R)
{
LL ans=0;
for (int d=1;d<=9;d++)
{
LL r=R/d;
ans+=r/9;
if (r%9>=d) ans++;
}
//ans-=R/18+R/8/9+(R/8%9==8)+R/14/9+(R/14%9==8);
ans-=R/54+(R%54>=36)+R/180+(R%180>=160)+R/126+(R%126>=112)+R/72+(R%72>=64);
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
LL l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",solve(r)-solve(l-1));
}
return 0;
}