bzoj 2405: 数字 数学

来源:互联网 发布:php编写的网站 编辑:程序博客网 时间:2024/06/05 16:15

题意

这里写图片描述
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;}
原创粉丝点击