版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/85205433
大意
求
的个数,其中
为
各数位之和
思路
直接把洛谷的题解扣过来
首先我们可以想到暴力,由于 最终的落点只有 ,所以我们可以移项得到 的时候, 就是一个满足要求的数
于是乎我们得到了下面这个30分的代码:
#include<cstdio>
#include<cctype>
using namespace std;long long f[1000001],L,R;
int t,s[1000001]={0,1,2,3,4,5,6,7,8,9};
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline long long read()
{
char c;int d=1;long long f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register long long x)
{
if(x<0)write(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
inline int S(long long x)//暴力算S
{
if(s[x]) return s[x];
return s[x]=x%10+S(x/10);
}
inline int D(long long x)//求D
{
if(x<10) return x;
return D(S(x));
}
inline bool check(long long x)
{
for(register int i=1;i<=9;i++)
if(x%i==0&&D(x/i)==i) return true;//枚举了d(i)后就只需要判断D(x/i)是否合法即可
return false;
}
signed main()
{
for(register int i=1;i<=1000000;i++) f[i]=f[i-1]+check(i);//前缀和预处理
t=read();
while(t--)
{
L=read();R=read();
write(f[R]-f[L-1]);putchar(10);//输出
}
}
满分的方法1:首先你得打一个表,然后你发现如果 满足要求则 也满足要求,为什么呢?因为
于是乎,我们只需预处理到22680就可以了,之后的按循环节处理
听大佬说,其实 具体证明我不会,但是打个表就能发现了嘛,对咯!
方法2: 容斥瞎搞,本蒟蒻不会啊。。。
代码
#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;long long f[22681],L,R,maxn;
int t;
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline long long read()
{
char c;int d=1;long long f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register long long x)
{
if(x<0)write(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
inline int D(long long x){return (x-1)%9+1;}//打了表之后发现的。。。
inline bool check(long long x)
{
for(register int i=1;i<=9;i++)
if(x%i==0&&D(x/i)==i) return true;
return false;
}
inline long long ask(long long x)
{
return x/22680*f[22680]+f[x%22680];//循环节处理
}
signed main()
{
for(register int i=1;i<=22680;i++) f[i]=f[i-1]+check(i);
t=read();
while(t--)
{
L=read();R=read();
write(ask(R)-ask(L-1));putchar(10);
}
}