“至少出现一次7”的数

(本来是列为转载的,但是原文算法那里有不可原谅的错误,愤慨之下,收归己有)

给定一个正整数n,写一个算法计算从1到n之间有多少“至少出现一次7”的数。例如n=20,那么有两个出现7的数:7,17。

算法

去掉个位的数字有N/10个,这也是个位为7的数的个数,包含出现多于一个7的情况,以下类推
再去掉十位的数字有N/100个,乘以9是十位为7的数的个数(个位不能再取7,所以乘9)
再去掉百位的数字有N/1000个,乘以81是百位为7的数的个数(个位或十位都不能再取7,所以乘9的平方)
依次类推。。。对于个位大于等于7的数字,最后的结果还要+1

例如2000内有7的个数=200+20*9+2*81=542, 2000/10 = 200 是个位出现7的数的个数,2000/200×9是十位出现7的情况,2000/1000×9×9是百位出现7的情况,个位小于7,不需要额外加1。

进一步解释:以2000作为例子,考虑个位为7的情况,从07,17,27一直到1997,个位为7的情况出现了200次(0到199);  考虑十位为7的情况,07x,17x,27x一直到197x,其中x代表除了7外的其他数字,所以十位为7的情况为20次(0到19)乘以9(个位的情况), 由于排除了个位是7的情况,所以不会跟第一种情况算重; 考虑百位为7的情况,07xx,17xx,所以百位为7的情况事2乘以9的平方。

为什么个位数大于等于7的话还要额外+1?譬如2018,因为2017事实上没有算入之前的几种情况,只算了(0到200).

这么一分析的话,代码就很简单了:

#include <iostream>
#include <cmath>
using namespace std;

int get7num(int n) {
	int p = 0;
	int num = 0;
	int bonus = (n%10 >= 7);
	while(n != 0) {
		num += (n/10)*pow(9,p);
		p++;
		n /= 10;
	}
	return num + bonus;
}

int main() {
	cout << get7num(2007) << endl;
	return 0;
}




 


发布了42 篇原创文章 · 获赞 6 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章