轉自:http://pandonix.iteye.com/blog/204840 Mark
N為正整數,計算從1到N的所有整數中包含數字1的個數。比如,N=10,從1,2...10,包含有2個數字1。
相信很多人都能立刻得出以下的解法:
for(n:N)
{
判斷n包含1的個數;
累加計數器;
}
這是最直接的解法,但遺憾的是,時間復雜程度為O(N*logN)。因為還需要循環判斷當前的n的各位數,該判斷的時間復雜程度為O(logN)。
接下來就應該思考效率更高的解法了。說實話,這道題讓我想起另外一道簡單的算法題:
N為正整數,計算從1到N的整數和。
很多人都采用了循環求解。然后利用初等數學知識就知道S=N*(N+1)/2,所以用O(1)的時間就可以處理。
再回到本道題目,同理應該去尋找到結果R與N之間的映射關系。
分析如下:
假設N表示為a[n]a[n-1]...a[1],其中a[i](1<=i<=n)表示N的各位數上的數字。
c[i]表示從整數1到整數a[i]...a[1]中包含數字1的個數。
x[i]表示從整數1到10^i - 1中包含數字1的個數,例如,x[1]表示從1到9的個數,結果為1;x[2]表示從1到99的個數,結果為20;
當a[1]=0時,c[1] = 0;
當a[1]=1時,c[1] = 1;
當a[1]>1時,c[1] = 1;
當a[2]=1時,c[2] = a[1] +1+ c[1] + x[1];
當a[2]>1時,c[2] = a[2]*x[1]+c[1]+10;
當a[3]=1時,c[3] = a[2]*a[1] +1+ c[2] + x[2];
當a[3]>1時,c[3] = a[3]*x[2]+c[2]+10^2;
......
以此類推
當a[i]=1時,c[i] = a[i-1]*...*a[1] +1+ c[i-1]+x[i-1];
當a[i]>1時,c[i] = a[i]x[i-1]+c[i-1]+10^(i-1);
代碼:
int main() { int N; cin>>N; int N1=N/10; int N2=N%10; int N3; int x=1; int y=10; int cnt=(N2==0?0:1); while(N1>0) { N3=N1%10; if (N3==0); else if (N3==1) { cnt=N2+1+x+cnt; } else { cnt=N3*x+cnt+y; } N2=10*N2+N3; N1=N1/10; x=10*x+y; y=y*10; } cout<<cnt<<endl; return 0; }