题目

和数书页有点类似,就直接数吧

#include<iostream>
using namespace std;
class q1
{
public:
size_t func(size_t num);
};
size_t q1::func(size_t num)
{
size_t count = 0, tmp;
while(num)
{
tmp = num;
while(tmp)
{
if(tmp%10 == 1)
++count;
tmp = tmp/10;
}
--num;
}
return count;
} int main()
{
q1 an;
size_t num = 0;
while(1)
{
cout<<"please input positive integer: ";
cin>>num;
cout<<num<<" to 0 include "<<an.func(num)<<" number 1 ."<<endl;
}
//num = 0xffffffff;
//cout<<num<<" to 0 include "<<an.func(num)<<" number 1 ."<<endl;
}

可循环输入,运行效果

显然,时间复杂度过高,一定有其他方法

先看 1 位数的情况。
如果 N = 3,那么从 1 到 3 的所有数字:1、2、3,只有个位数字上可能出现 1,而且只出现 1 次,进一步可以发现如果 N 是个位数,如果 N>=1,那么 f(N)都等于 1,如果 N=0,则 f(N为 0。
再看 2 位数的情况。
如果 N=13,那么从 1 到 13 的所有数字:1、2、3、4、5、6、7、8、9、10、11、12、13,个位和十位的数字上都可能有 1,我们可以将它们分开来考虑,个位出现 1 的次数有两次:1 和 11,十位出现 1 的次数有 4 次:10、11、12 和 13,所以 f(N)=2+4=6。要注意的是 11 这个数字在十位和个位都出现了 1,但是 11 恰好在个位为 1 和十位为 1 中被计算了两次,所以不用特殊处理,是对
的。再考虑 N=23 的情况,它和 N=13 有点不同,十位出现 1 的次数为 10 次,从 10 到 19,个位出现 1 的次数为 1、11 和 21,所以f(N)=3+10=13。通过对两位数进行分析,我们发现,个位数出现 1 的次数不仅和个位数字有关,还和十位数有关:如果 N 的个位数大于等于 1,则个位出现 1 的次数为十位数的数字加 1;如果N 的个位数为 0,则个位出现 1 的次数等于十位数的数字。而十位数上出现 1 的次数不仅和十位数有关,还和个位数有关:如果十位数字等于 1,则十位数上出现 1 的次数为个位数的数字加 1;如果十位数大于 1,则十位数上出现 1 的次数为 10。
 
接着分析 3 位数
如果 N = 123:
个位出现 1 的个数为 13:1, 11, 21, …, 91, 101, 111, 121
十位出现 1 的个数为 20:10~19, 110~119
百位出现 1 的个数为 24:100~123
f(23)= 个位出现 1 的个数 + 十位出现 1 的个数 + 百位出现 1 的次数 = 13 + 20 + 24 = 57;
根据上面的一些尝试,下面我们推导出一般情况下,从 N 得到 f(N)的计算方法:
假设 N=abcde,这里 a、b、c、d、e 分别是十进制数 N 的各个数位上的数字。如果要计算百位上出现 1 的次数,它将会受到三个因素的影响:百位上的数字,百位以下(低位)的数字,百位(更高位)以上的数字。
如果百位上的数字为 0,则可以知道,百位上可能出现 1 的次数由更高位决定,比如 12 013,则可以知道百位出现 1 的情况可能是 100~199,1 100~1 199,2 100~2 199,…,11 100~11 199,一共有 1 200 个。也就是由更高位数字(12)决定,并且等于更高位数字(12)×当前位数(100)。
如果百位上的数字为 1,则可以知道,百位上可能出现 1 的次数不仅受更高位影响,还受低位影响,也就是由更高位和低位共同决定。例如对于 12 113,受更高位影响,百位出现 1 的情况是 100~
199,1 100~1 199,2 100~2 199,…,11 100~11 199,一共 1 200个,和上面第一种情况一样,等于更高位数字(12)×当前位数(100)。但是它还受低位影响,百位出现 1 的情况是 12100~12 113,一共14 个,等于低位数字(13)+1。
如果百位上数字大于 1(即为 2~9),则百位上可能出现 1的次数也仅由更高位决定,比如 12 213,则百位出现 1 的可能性为:100~199,1 100~1 199,2 100~2 199,…,11 100~11 199,12 100~12 199,一共有 1 300 个,并且等于更高位数字+1(12+1)×当前位数(100)。
所以利用这个规律我们可以写出新的更高效的算法
#include<iostream>
using namespace std;
class q1
{
public:
size_t func(size_t num);
size_t func1(size_t num);
size_t equ(size_t befor, size_t num);
};
size_t q1::func(size_t num)
{
size_t count = 0, tmp;
while(num)
{
tmp = num;
while(tmp)
{
if(tmp%10 == 1)
++count;
tmp = tmp/10;
}
--num;
}
return count;
} size_t q1::func1(size_t num)
{
size_t Ncount = 0;
size_t Nlower = 0;
size_t Ncurrent = 0;
size_t Nhigher = 0;
size_t circle = 1;
while(num/circle != 0)
{
Nlower = num - (num/circle)*circle;
Ncurrent = (num/circle)%10;
Nhigher = num/(circle*10); switch(Ncurrent)
{
case 0:
Ncount += Nhigher*circle;//当前位是0
break;
case 1:
Ncount += Nhigher*circle + Nlower;//当前位是1
break;
default:
Ncount += (Nhigher+1)*circle;//当前位置不是0或1
break; }
circle *= 10;
}
return Ncount;
} int main()
{
q1 an;
size_t num;
while(1)
{
cout<<"please input positive integer: ";
cin>>num;
cout<<num<<" to 0 include "<<an.func1(num)<<" number 1 ."<<endl;
}
}

运行一下,发现即使数字很大相当快,编程之美作者牛逼

第二问,作者的答案是

然而,将n = 1 111 111 110输入

虽然很接近,但是最大N确实不在此点,而且经过手动校验,也不在这附近。

使用图像法,只要找出y = func1(N)和y = x两个函数交点即可。 由实践可知交点不止一个,并且有交点非整数。

进行遍历对比,效率很低,发现了存在这么多 N = func(N)

程序跑到这里,已经被操作系统强行终止了,但是我们知道在1~2^32 - 1 这个区间范围内应该还有更大的数字满足N = func1(N),现在遍历已经行不通了,所以建议使用MATLAB将 y=x 和 y = func1(x)这两个曲线绘出来,然后在估算交点区间,在小区间内进行更高效的遍历,这样可以快速找出答案。

编程之美Q1的更多相关文章

  1. 编程之美2014挑战赛 复赛 Codehunt平台试题答案

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  2. LeetCode:Climbing Stairs(编程之美2.9-斐波那契数列)

    题目链接 You are climbing a stair case. It takes n steps to reach to the top. Each time you can either c ...

  3. 编程之美2.5:寻找最大的K个数

    编程之美2.5:寻找最大的K个数 引申:寻找第k大的数: 方法一: // 选择第k大的数(通过改进快速排序来实现) public static void SelectShort(int[] array ...

  4. 24点C++程序实现 编程之美1.16

    解法1,对于任意输入的四个数字,给出一个24点的解法,若无解,则没有输出. 原理参照下图(编程之美原书) 代码如下,仅供参考 // 1.16.cpp : Defines the entry point ...

  5. 2017“编程之美”终章:AI之战勇者为王

    编者按:8月15日,第六届微软“编程之美”挑战赛在选手的火热比拼中圆满落下帷幕.“编程之美”挑战赛是由微软主办,面向高校学生开展的大型编程比赛.自2012年起,微软每年都在革新比赛命题.紧跟时代潮流, ...

  6. Python编程之美:最佳实践指南PDF高清完整版免费下载|百度云盘|Python新手到进阶

    百度云盘:Python编程之美:最佳实践指南PDF高清完整版免费下载 提取码:1py6 内容简介 <Python编程之美:最佳实践指南>是Python用户的一本百科式学习指南,由Pytho ...

  7. 生成CPU使用率 sin 曲线 控制cpu使用率 编程之美

    入职Oracle 以后想着把之前写过的<编程之美>中控制CPU使用率曲线的程序再写一边, 可是总是由于入职须要学习的东西太多, 没有时间. 程序早就写好了. 最终有机会贴出来了.o(∩∩) ...

  8. 编程之美:1.9高效率安排见面会 图的m着色问题 回溯法

    原书问题,可以转换为图的m着色问题 ,下面该问题的代码 这里有参考ppt与code,免积分载 http://download.csdn.net/detail/u011467621/6341195 // ...

  9. 编程之美2015初赛第一场 hihoCoder #1156 : 彩色的树(染色问题)

    #1156 : 彩色的树 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定一棵n个节点的树,节点编号为1, , …, n.树中有n - 1条边,任意两个节点间恰好有一条 ...

随机推荐

  1. 微信小程序API接口封装

    @ 目录 一,让我们看一下项目目录 二,让我们熟悉一下这三个文件目的(文件名你看着办) 三,页面js中如何使用 今天的API的封装,我们拿WX小程序开发中,对它的API (wx.request)对这个 ...

  2. 区块链开发学习第三章:私有链上部署helloBlockchain简单合约

    前面讲了部署私有链以及新增账户,现在进行到了部署合约了,此操作真是踩了无数无数无数的坑,到写文章为止确实是已经部署好了,但是还有些坑是还没有解决的! 一.Solidity编译器 开始的时候用的http ...

  3. 【接口】HttpClient 处理get和post请求(二)(2019-07-14 18:41)

    一.环境准备 1.导入httpClient依赖包 <dependency> <groupId>org.apache.httpcomponents</groupId> ...

  4. docker容器命令(一)

    容器命令 创建容器:docker run 参数: -it 交互 -d 后台 –name 容器名 -p 主机端口:容器端口 (主机端口映射到docker端口) docker run --name cen ...

  5. 解决mac主机无法与 Docker容器互通问题

    方法很多,这里我说一下使用 docker-connector解决这个问题 这是一个github开源项目docker-connector  1. Mac 通过 brew 安装 docker-connec ...

  6. 登录、注销&用户和用户组管理

    登录.注销 # 立刻关机 shutdown -h now # 1分钟后,关机 shutdown -h 1 # 立刻重启 shutdown -r now # 2分钟后,重启 shutdown -r 2 ...

  7. sklearn模型保存与加载

    sklearn模型保存与加载 sklearn模型的保存和加载API 线性回归的模型保存加载案例 保存模型 sklearn模型的保存和加载API from sklearn.externals impor ...

  8. 什么是齐博x1标签

    X系列的标签跟V系列的标签区别还是很大的.在V系列的时候,只有一种很简单的标签比如$label[XXXX]以前的标签相对现在的来说太简单的点,所以在功能上也比较受限.X系列目前有几下几种标签 {qb: ...

  9. FZU ICPC 2020 寒假训练 4 —— 模拟(一)

    P1042 乒乓球 题目背景 国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及.其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役.华华 ...

  10. 博主日常工作中使用的shell脚本分享

    前言: 今天给大家分享一篇在我工作中常用的一个shell脚本,里面有一些我们常用到的shell操作.该脚本用于本地电脑和服务器交互上,实现以下功能: 自动拉取自己个人电脑上的源码到服务器上yocto包 ...