NYOJ 514 1的个数

地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=514

思路1:

有篇博文写的是统计二进制中1的个数和,这篇是统计区间内十进制的1的个数和。

先讨论下1到n间的1的个数和。给你一个数如:384,求1~384的1的个数之和。

那么我只需求出1~300中1的个数和+1~80中1的个数和+1~4中1的个数和。

1~4的1的个数为1,1~80中1的个数为101(十位数)+8*100(个位数)----十位数有10,11,12,13....19(共10个数--其中11后面的1作为个位数看待),个位数为1,11,21,31...71,共有8个1,同理可得1~300中的1的个数102(百位数--只有以1开头的数)+3*101(十位数)+30*100(个位数)。

要特别注意的是当你的求的这一位是1的时候要特别处理,比方说N=187,这个时候百位上的1的个数就不是100了,而是88个即N%102+1。

化简以一下,求1~a000000(假设共有k位)中1的个数(a!=1),那么个数为:10k-1+a*10k-2+10*a*10k-3+....+10k-1*a*100=10k-1+a*(k-1)*10k-2

那么代码就很简单了,下面Count(n)是求1到n中1的个数和。

那么我要求[a,b]间所有的1的个数和,那么就相当于求Count(b)-Count(a-1)的值。

10k-1+a*(k-1)*10k-2 这个公式如何用代码表示,还不够清楚,,,,正在研究。。。。

代码如下:

 1 #include<iostream>  
 2 using namespace std;  
 3 int low,high;  
 4 int Pow[10]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};  
 5 int Count(int n)  
 6 {   int digit=0,temp=n,sum=0;  
 7     while(temp)  
 8     {   if(temp%10>1) sum+=Pow[digit];  
 9         else if(temp%10==1) sum+=n%Pow[digit]+1;  
10         sum+=temp%10*digit*Pow[digit-1];  
11         temp/=10,digit++;  
12     }  
13     return sum;  
14 }   
15 int main()  
16 {   while(cin>>low>>high,low+high)  
17     {   if(low>high) swap(low,high);    //swap函数用在std空间,algorithm头文件。。。
18         cout<<Count(high)-Count(low-1)<<endl;  
19     }  
20     return 0;  
21 }  

 

 

 

思路2:

此题就是统计a~b之间有多少个1。显然不能暴力,因为数据很大,暴力的结果是超时。

所以要充分考虑数的构成,特别是权。个位数的1次数是1,十位数的1次数就是10,百位数的1次数就是100,依次类推……

可以算出0~b之间1的个数,0~(a-1)之间1的个数,相减即是a~b之间1的个数。

统计个位数,再把个位数消失掉,统计十位数(此时的十位数处于个位数的位置,但是权值是10),和刚才处理个位数一样的方法。所以用递归!

比如497,个位数会有个1(491),当个位数是1是,前面两位可以从0~48(49个,0相当于没有,此时是整数1)。所以sum =1+49 = 50。

然后让个位数消失(497/10-1),减1的原因是(统计个位数后的工作是把4,9,1分别出现次数统计过了)。然后看48,8的位置上的1的个数是1*10(权值是10),然后4的位置上可以从0~3共4*10个。所以sum = 50 + 10 + 40 = 100.

然后统计百位数(48/10 - 1)就是3了。显然只有一个1,权值是100.所以sum = 100 + 1* 100 = 200。

代码如下:

 1  
 2 #include<stdio.h>
 3 int d[10],value;
 4 void fun(int n);
 5 int main()
 6 {
 7     int i,t,a,b;
 8     while(scanf("%d%d",&a,&b)&& (a+b))
 9     {
10         if(a>b)
11         {t = a;  a = b;  b = t;}
12         value = 1;
13         for(i = 0 ; i < 10 ; ++i)
14         d[i] = 0 ;
15         fun(b);
16         value = -1;
17         fun(a-1);
18         printf("%d\n",d[1]);                               
19     } 
20     return 0;    
21 }
22 void fun(int n)
23 {
24     int one,ten,i;
25     if(n<=0) return ;
26     one = n % 10;
27     n /= 10;
28     ten = n;
29     for(i = 0 ; i <= one ; ++i )
30       d[i] += value;  
31     while(ten)
32     {
33        d[ten%10] += (one+1)*value;
34        ten /= 10;          
35     }
36     for(i = 0 ;i < 10 ; ++i)
37       d[i] += n*value;
38       d[0] -= value;
39       value *= 10;
40       fun(n-1); 
41 }        

 

 

 

 

 

posted on 2012-08-20 08:49  mycapple  阅读(561)  评论(0编辑  收藏  举报

导航