统计1到N之间所有十进制数中数字1的个数。
这是一道十分有趣的题,例如N为12的时候,输出是5,因为从1到12,总共有1,10,11,12中包含数字1,总共是5个。
最傻逼的办法当让是直接枚举,即N^2的方法,对于小数据,是可以容忍的,但是此题中N最大可以达到2^30次方,因此
该方法不行。
我觉得这一题更偏数学一点,只要找到了递推公式,变成是非常简单的。
我们用part1来表示1-99..99中所包含的1的个数
1-9中有只有1一个
1-99总共有20个
递推公式很容易得到,part1[n] = part1[n-1]*10 + 10^(n-1),其中N表示9的个数。
对于N,我们从N的个位数开始往高位递推。
如下图所示

假设我们已经进行到n位,我们用part2表示前n位的结果。N的第n位数字是t,那么前N位的结果
part2[n] = part2[n-1] + t*part1[n-1]。
如果t = 1,那么还要再加上N mod (10^(n-1))的结果,如果t>1,加上10^(n-1)的值即可。
代码如下:
#include<iostream> using namespace std; int main() { unsigned long n; unsigned long part1,part2,ans,yu; unsigned long base = 1; unsigned int tmp; cin >> n; base = 1; //用来表示10的几次方 ans = 0; //用来存储最终的结果 yu = n%10; //用来表示N mod (10^(n-1))的结果,即余数 part1 = 1; //表示part1 if (yu >= 1) ans = 1; part2 = ans; //表示part2 n = n/10; while (n!=0){ tmp = n % 10; base = base*10; ans = tmp*part1 + part2; if(tmp == 1) ans = ans + yu + 1; else if (tmp > 1) ans = ans + base; part1 = part1*10 + base; part2 = ans; n = n/10; yu = tmp*base + yu; } cout << ans<<endl; return 0; }
浙公网安备 33010602011771号