2018.12.22【NOIP提高組】模擬B組 JZOJ 2700 數字
阿新 • • 發佈:2018-12-22
大意
求
的個數,其中
為
各數位之和
思路
直接把洛谷的題解釦過來
首先我們可以想到暴力,由於 最終的落點只有 ,所以我們可以移項得到 的時候, 就是一個滿足要求的數
於是乎我們得到了下面這個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);
}
}