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 }