BZOJ 2405 数字

来源:互联网 发布:中船重工 知乎 编辑:程序博客网 时间:2024/05/29 17:59

Description

Input

第一行一个整数T,表示数据组数。

以下每一行两个数LR(保证区间合法),代表询问[L, R]

Output

输出T行,每行一个数,表示在这个区间内小D喜欢的数出现了多少次。

你的输出当且仅当和标准输出一样才能得该测试点满分。

Sample Input

3

1 5

3 9

8 8

Sample Output

2

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 longll 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;}