暴力法
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin>>n;
int a[10]= {0};
for(int i=1; i<=n; i++) {
int t=i;
while(t) {
a[t%10]++;
t=t/10;
}
}
for(int i=0; i<10; i++) {
cout<<i<<" : "<<a[i]<<endl;
}
return 0;
}
递归法
参考文章:
1-1统计数字问题(详解)
步骤一:
先求键盘输入的数n是一个几位数,设位数为len
公式log(n)+1;
可用cmath里的函数:double log10(double x)来求解
步骤二:
划分区间,然后相加
把数n尽可能的划分为较少的区间。【按位数划分】
223,可划分成00-99,100到199(两个区间)
3333,可划分为000-999,1000到1999,2000到2999(三个区间)
后两个区间比第一个区间分别多了1000个1和2,其余数字相同。
在这每一个区间内(除了最高位)0-9出现的次数是**(len-1)*10^(len-2)**----(列举一下可发现规律)
现在我们知道了每个区间的0-9出现的次数,该求区间数了:
如233区间数就是2,3333的区间数就是3,所以数n的区间数p是n/(10^(len-1))
综上,如3333,从000-2999(除了最高位)0到9的每个数的个数为p(len-1)10^(len-2)
以3333为例,上面的那个公式都没有计算千位数出现的次数,而是把划分好的区间计算完了,3333分为三个区间,区间数3乘以0-9出现的次数,其实就是计算了三次000-999出现的次数。
步骤三:
最高位相加
如3333,上一步我们已经算好从000到2999,(除了最高位)0到9每个数的和了
现在来算最高位
最高位(第4位)的数有0、1、2、3
0:0000-0999共1000个
1:1000-1999共1000个
2:2000-2999共1000个
3:3000-3333共333+1个
设最高位为m可得代码如下
for(int i=0;i<m;i++){
c[i]+=pow(10.0,len);
}
c[m]+=1+n%((int)pow(10.0,len-1));
步骤四:
递归
处理完3333的000-2999个数以及3作为第len位的情况剩下333递归处理333
即要处理t=n%(10^(len-1))
注意:
(1)若t为0,比如200,此时c[0]要加len-1也就是2!
若数10,则t为0,c[0]要加len-1,也就是1,
然后结束递归.
(2)若t不为0,这里特判一下,若lenT!=len-1说明是诸如10010这种情况,中间两个0还是要处理的,
c[0]+=(len-lenT-1)*(t+1)
fill()函数参数:fill(first,last,val);
// first 为容器的首迭代器,last为容器的末迭代器,val为将要替换的值。
注意: fill()中 ,它的原理是把那一块单元赋成指定的值,也就是说任何值都可以
memset(),则是将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,即0 、1
#include<bits/stdc++.h>
using namespace std;
//统计数字问题 递归法
int c[10];
void solve(int n) {
int len=log10(n)+1;//数n的位数
int p=n/((int)round(pow(10.0,len-1)));//最高位的值
for(int i=0; i<10; i++)
c[i]+=p*(len-1)*(int)round(pow(10.0,len-2));
for(int i=0; i<p; i++)
c[i]+=(int)round(pow(10.0,len-1));
int t=(int)round(pow(10.0,len-1));
t=n%t;
if(t==0) {
c[p]++;//最高位+1
c[0]+=len-1;//0位+len-1
return ;
}
int lent=log10(t)+1;
if(lent!=len-1) {
c[0]+=(len-lent-1)*(t+1);
}
c[p]+=t+1;
return solve(t);
}
int main() {
int n;
//下面做了一个循环输入的设计 当然也可以删除
while(cin>>n) {
fill(c,c+10,0);
int len=log10(n)+1;
solve(n);
for(int i=0; i<len; i++) {
c[0]-=(int)round(pow(10.0,i));
}
for(int i=0; i<10; i++) {
cout<<i<<" : "<<c[i]<<endl;
}
}
return 0;
}