1. 程式人生 > >51nod 1009 數字1的數量 (統計1的總個數,好題)

51nod 1009 數字1的數量 (統計1的總個數,好題)

給定一個十進位制正整數N,寫下從1開始,到N的所有正數,計算出其中出現所有1的個數。 例如:n = 12,包含了5個1。1,10,12共包含3個1,11包含2個1,總共5個1。 Input
輸入N(1 <= N <= 10^9)
Output
輸出包含1的個數
Input示例
12
Output示例
5

思路,根據n的位數,我們統計一下個位、十位、百位,每一位上1所作出的貢獻,然後根據每個位是大於1,小於1,還是等於1,進行分類討論!!!

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int sum[20];
int getlen(int n)
{
	int num=0;
	while(n) {
		n=n/10;
		num++;
	}
	return num;
}

int main()
{
	int n,i,j,t1,t2,len,ans;
	cin>>n;
	len=getlen(n);
	sum[1]=n/10;
	if(n%10>=1) sum[1]++;
	for(i=2,t1=10,t2=100;i<=len;i++,t1=t1*10,t2=t2*10) {
		if(n/t1%10>1) {
			sum[i]=n/t2+1;
			sum[i]=sum[i]*t1;
		}
		else if(n/t1%10==1) {
			sum[i]=n/t2;
			sum[i]=sum[i]*t1+n%t1+1;
		}
		else {
			sum[i]=n/t2;
			sum[i]=sum[i]*t1;
		}
	} 
	ans=0;
	for(i=1;i<=len;i++) ans+=sum[i];
	cout<<ans<<endl;
	return 0;
} 


下面是從別人那盜來來的題解,跟我的思路差不多,方便以後複習用:

1位數的情況:

在解法二中已經分析過,大於等於1的時候,有1個,小於1就沒有。

 2位數的情況:

N=13,個位數出現的1的次數為2,分別為1和11,十位數出現1的次數為4,分別為10,11,12,13,所以f(N) = 2+4。

N=23,個位數出現的1的次數為3,分別為1,11,21,十位數出現1的次數為10,分別為10~19,f(N)=3+10。

由此我們發現,個位數出現1的次數不僅和個位數有關,和十位數也有關,如果個位數大於等於1,則個位數出現1的次數為十位數的數字加1;如果個位數為0,個位數出現1的次數等於十位數數字。而十位數上出現1的次數也不僅和十位數相關,也和個位數相關:如果十位數字等於1,則十位數上出現1的次數為個位數的數字加1,假如十位數大於1,則十位數上出現1的次數為10。

 3位數的情況:

N=123

個位出現1的個數為13:1,11,21,…,91,101,111,121

十位出現1的個數為20:10~19,110~119

百位出現1的個數為24:100~123

 我們可以繼續分析4位數,5位數,推匯出下面一般情況: 

假設N,我們要計算百位上出現1的次數,將由三部分決定:百位上的數字,百位以上的數字,百位一下的數字。

如果百位上的數字為0,則百位上出現1的次數僅由更高位決定,比如12013,百位出現1的情況為100~199,1100~1199,2100~2199,…,11100~11199,共1200個。等於更高位數字乘以當前位數,即12 * 100。

如果百位上的數字大於1,則百位上出現1的次數僅由更高位決定,比如12213,百位出現1的情況為100~199,1100~1199,2100~2199,…,11100~11199,12100~12199共1300個。等於更高位數字加1乘以當前位數,即(12 + 1)*100。

如果百位上的數字為1,則百位上出現1的次數不僅受更高位影響,還受低位影響。例如12113,受高位影響出現1的情況:100~199,1100~1199,2100~2199,…,11100~11199,共1200個,但它還受低位影響,出現1的情況是12100~12113,共114個,等於低位數字113+1。