//Uva1225
//求数字0-9在前n个正整数中出现的次数(1<=n<=10000)
//设n是length位数,设num为n最高位的数,设m=num*(10^(length-1)),设d是n的后length-1位数组成的数,则m=n-d。
//比如,n=123456789,n是9位数(length=9)。则m=100000000,d=23456789。
//d也可以当成是新的n,拆成两部分,则:n=1*10^8+2*10^7+3*10^6+...+8*10+9。
//将n倒序,将其倒序后的每一位储存在数组input中,从input[1]开始,令input[0]=0。
//比如:input[]={0,9,8,7,6,5,4,3,2,1},则n=input[1]+input[2]*10^1+...+input[i]*10^(i-1)+...+input[9]*10^8。
//则m=input[9]*10^8=100000000。考虑m,m是9位数(length=9),最高位为num=1。
//先来计算在前m个正整数中,0-9出现了的多少次,将结果储存在数组ans中。(calculate(1,9,ans))。
//可想象这样一个数字排列:
//100000000
// 99999999
// 99999998
// 。。。
// 10000000
// 9999999
// 。。。
// 2
// 1
//即将1-m从下至上排列出来。
//可将其写成如下格式:
//100000000
//099999999
//099999998
// 。。。
//010000000
//009999999
// 。。。
//000000002
//000000001
//后length-1列中,每一列0-9出现次数相同,则for(i:0->9) ans[i]+=num*10^(length-1)*(length-1)/10。
//然后计算首位数字的情况。for(i:1->num-1) ans[i]+=10^(length-1)。还要ans[num]+=1。
//因为0被多记录了(9+99+999+...+99999999)次,应再减去。ans[0]-=(10^(length-1)-1)/9-(length-1)。
//以此类推。其实感觉可以从排列组合的角度解决此问题。
#include <iostream>
#include <math.h>
using namespace std;
void calculate(int num,int size,int* array); //
int n=0;
int main()
{
while(cin >>n)
{
int length=0;
int ans[10]={0}; //ans[i]:i出现的次数。
int input[10]={0}; //input[i]:n的第i位数。
do //将n的每一位数储存在input数组中。
{
input[++length]=n%10;
}
while(n/=10);
for(int i=1;i<=length;++i)
{
if(input[i])
{
calculate(input[i],i,ans);
}
for(int j=1;j<i;++j)
{
if(input[j])
{
ans[input[i]]+=input[j]*pow(10,j-1);
}
}
}
for(int j=0;j<10;++j)
{
cout << j << " 出现的次数为: " << ans[j] << endl;
}
cout << endl;
}
return 0;
}
void calculate(int num,int size,int* array)
{
for(int i=0;i<10;++i)
{
array[i]+=pow(10,size-2)*num*(size-1);
}
for(int j=1;j<num;++j)
{
array[j]+=pow(10,size-1);
}
array[num]+=1;
array[0]+=(size-1)-(pow(10,size-1)-1)/9;;
}
Uva1225 求数字0-9在前n个正整数中出现的次数(1<=n<=10000)
最新推荐文章于 2022-04-09 09:32:20 发布