输入2个数N和D,求1-N这N个整数中,D出现了多少次
(我很友好,没有恶意)这是一道很fw的题,做不出来的连fw都不如。【偷笑表情包】
看到这道题,你的第一反应绝对是“哇!这题这么水的吗!?好简单啊!”
然后,你绝对就会开始疯狂敲代码:咚咚咚!咚咚咚咚!!!咚咚————
最后,你的代码一定是这样:
#include
using namespace std;
int d,n;
int tongji(int);
int main()
{
cin>>d>>n;
int sum = 0;
for(int i = 1;i<=n;i++)
{
sum += tongji(i);
}
cout<
接着,你一定会自信满满的将代码ctrl+c,点到网站界面,ctrl+v,心里念:“见证奇迹吧!赶快AC吧!”最后,奇迹有没有发生呢?......
相信99.99%的人都会做以上操作,并且无一例外,全是Runtime Error , Wrong Answer , Time Limit Error......想AC?你这个代码,下辈子都别想AC!那么,这道题的真正的AC代码究竟是什么?接下来,我将带领你们,将这道题,搞成AC!
我们需要先分析一下上面代码的错因:
99.99%的人都没注意到题目下面的数据规模:1<=N<=10的16次方
10的16次方!!!!!!!!!!!!!!!!!!!!
10000000000000000!!!!!!!!!!!!!!!!!!!!
恐怖如斯................................................
所以,上面的代码时间会超限。
那么,怎么解决时间超限呢?
肯定是优化代码啊!!!!!
那么......
怎么优化代码呢?
额.....................................啊......................................
当然,先别急,我告诉你!
我们可以找一找D出现的规律:
怎么找呢?
逐位去找
我们先拿一组测试用例来做分析:
比如:D=3,N=12345
1.看个位
通过分析可知,假如将每10个数视为一个小阶段,比如1-10是个阶段,11-20是个阶段,那么,每个阶段数字的个位都会出现一次“3”.
而12345一共有1234个完整的阶段,所以1-12340中各位出现了1234次“3”。
但是,你一定发现了,数字12343的个位也出现了“3”,所以,1-12345中个位就出现了1234+1=1235次“3”.
2.看十位
通过分析可知,假如将每100个数视为一个小阶段,比如1-100是个阶段,101-200是个阶段,那么,每个阶段数字的十位都会出现10次“3”.(30、31、32、33、34、35、36、37、38、39)(个位的那个“3”在之前第一步的“看个位”中已经算过,这里不再计算)
而12345一共有123个完整的阶段,所以1-12300中各位出现了1230次“3”。
但是,你一定得发现了,数字12330-12339中的十位出现了10次“3”,所以,1-12345中十位就出现了1230+10=1240次“3”。
3.看其他位
这里其他位的分析方法和十位百位差不多,所以不再过细讲解。
百位出现1246次“3”,千位出现1000次“3”,万位出现0次“3”
最后,只要将各个位出现“3”的次数相加,得到答案:4721,问题就解决了!!!!!
【高兴表情包】【欢呼表情包】
那么,最后的最后,请出我们的————AC代码!!!
#include
using namespace std;
long long int d,n;
int main()
{
cin>>d>>n;
int sum = 0;
for(int i = 1;i<=n;i = i*10)
{
sum += n/(i*10)*i;
int tmp = (n/i)%10;
if(tmp>d) sum += i;
else if(tmp==d)
{
if(i==1) sum += 1;
else sum += n%i+1;
}
}
cout<