P1239 计数器

题意:就是求从1到n间,1~9一共出现的次数

这道题直接暴力是不科学的,因为N有 1e9;

然后我就看到了一个很好的从贡献思考的方法;

——>转自洛谷学神的方法:

楼下dalao都是数学方法和数位dp,看的本蒟蒻心慌慌

如果对高级方法难以理解的话,这里提供一种简单方法,虽然效率比dalao们差很多,但是对于本题已经够了

对于每一个数x,可以分为x/10000和x%10000两个部分(也就是前几位和后4位)

那么对于中间很大一段数字,同样的前几位会重复出现一万次,后4位就是0000-9999

所以对于中间这一段,可以枚举前几位,贡献值乘以1万,然后每枚举一个,0-9的出现次数加上4000就是后4位的贡献值

(0000-9999总共4万个数码,每个数码出现次数都相等)

然后前面的1-9999和最后一截 前几位没出现1万次的数暴力算就行了

这份代码绝对容易理解,而且对于这题也是0ms(自己理解了比较久。。。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
const int N = ; using namespace std;
int n,a[],b[]; void f(int x) //计算一个数中每个数码出现次数
{
while( x>) a[x%]++,x/=;
} int main(){
scanf("%d",&n);int x = n/N;
if(n<) //计算一个数中每个数码出现次数
{
for(int i=; i<=n; i++)
f(i);
}
else
{
for(int i=; i<N; i++)f(i); //算出前面的1-9999
for(int i=; i<x; i++) //算中间一段,方法如上面所述
{
memset(b,,sizeof(b));
int y = i;
while(y>) b[y%]++,y/=;
for(int i=; i<; i++)a[i]+=b[i]*N;
}
for(int i=; i<; i++)a[i]+=*(x-);//后4位的贡献值一次性加上,不用一个一个加
for(int i=x*N; i<=n; i++)f(i); //算最后的一些数
}
for(int i=;i<;i++)
printf("%d\n",a[i]); //输出
return ;
}

最新文章

  1. java小结
  2. YAML 技术研究
  3. 陈朱兴-js写法【案例】:
  4. 【转】javascript性能优化-repaint和reflow
  5. 399. Evaluate Division
  6. log4net学习目录
  7. hdu4352(数位dp)
  8. Invalid property &#39;url&#39; of bean class [com.mchange.v2.c3p0.ComboPooledDataSource]
  9. bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪
  10. Ubunto使用 码云 创建项目
  11. 用HTML5+原生js实现的推箱子游戏
  12. IE的浏览器模式、文本模式
  13. 主机性能监控之wmi 获取系统信息及内存性能信息
  14. DataUtils对Connection的获取、释放和关闭的操作学习
  15. facebook&#39;s HipHop for PHP: Move Fast
  16. QWidget设置背景图
  17. Spark2.3文档翻阅的一点简略笔记(WaterMarking)
  18. 【java】解析JToolBar类的使用
  19. java中的元数据
  20. Flask基础应用

热门文章

  1. 阿里云nas使用记录
  2. 【Sublime】设置显示编码格式
  3. 【iOS】the executable was signed with invalid entitlements
  4. 深入理解java内存模型--读书笔记
  5. java课堂 动手动脑2
  6. 值得花费一周研究的算法 -- KMP算法(indexOf)
  7. macos Mojave 出现网络出错 Frame Check Sequence: Bad checksum
  8. js学习之数据类型
  9. java实现发短信功能---腾讯云短信
  10. 使用JMS接口接入WebSphere MQ消息