Description
Input
第一行一个整数T,表示数据组数。
以下每一行两个数L、R(保证区间合法),代表询问[L, R]。
Output
输出T行,每行一个数,表示在这个区间内小D喜欢的数出现了多少次。
你的输出当且仅当和标准输出一样才能得该测试点满分。
Sample Input
3
1 5
3 9
8 8
1 5
3 9
8 8
Sample Output
2
2
0
2
0
HINT
L,R<=10^18,T<=20
Source
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~打表找规律+暴力~
打个表,就能发现a[n%22680]=a[22680](肉眼观察法显然不可行TAT),其中22680为lcm(1,2,...9)*9,a[i]为i是否为喜欢的数,然后暴力预处理出<=22680的答案,直接解即可。
注意区分long long和int!
学会了编程找规律……还是挺神奇的,考试时候怎么就肉眼观察了呢2333~
#include<cstdio>
#include<iostream>
using namespace std;
#define ll long long
ll t,n,m,a[22681];
ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void init()
{
for(int i=1;i<=22680;i++)
if((ll)(((i-1)%9)+1)*i<=22680) a[(((i-1)%9)+1)*i]=1;
for(int i=2;i<=22680;i++) a[i]+=a[i-1];
}
ll cal(ll u)
{
return u==-1 ? 0:a[22680]*(u/22680)+a[u%22680];
}
int main()
{
t=read();
init();
while(t--)
{
n=read()-1;m=read();n=cal(n);m=cal(m);
printf("%lld\n",m-n);
}
return 0;
}