uva 11038 - How Many O's?

想法:
  將問題簡化為求1~m 0的總數,以及1~n 0的總數,然後最後再相減。
  求1~n 0的總數,要將n分別算每個位數0的個數,舉例如30324:

  • 先從右邊第一位'4'開始,其左邊為3032,表示1~30320在"第一位"總共有3032*1=3032個0
  • 換第二位數'2',其左邊為303,表示總共有303*10(右邊有1位)=3030個0
  • 再換第三位數也是一樣,30*100=3000個0,
  • 注意第四位數為'0',因此原本應該是3*1000,但第3個1000其實只到324而以,所以為2*1000+324+1=2325個0 (+1是因為別忘了0~324是325個)
  • 最後一位'3',它是最高位數,因此不會有0
  • 所以總共為3032+3030+3000+2325=11387
因此,此演算法從最低位(i==1)開始到最高位(i==k)結束,如果第i位不為0,直接左邊數字x10^(i-1),如果第i位為0,那麼(左邊數字-1)x10^(i-1)+右邊數字+1,最後把每位數的0總數加起來即可。
 1 #include <cstdio>
 2 using namespace std;
 3 typedef long long int llt;
 4 
 5 llt sum0(llt n)
 6 {
 7     llt N = n, sum = 0;
 8     int left = 1, mid, right = 1;
 9     while(N >= 10)
10     {
11         mid = N % 10;
12         N /= 10;
13         if(mid) sum += (N * left);
14         else sum += ((N-1) * left + n % right + 1);
15         left *= 10;
16         right *= 10;
17     }
18     return sum;
19 }
20 
21 int main()
22 {
23     llt m, n;
24     while(scanf("%lld%lld", &m, &n) == 2 && m >= 0)
25     {
26         llt ans = sum0(n) - sum0(m-1);
27         if(m == 0) ans ++;  // 函数是从1~m, 如果m==0会少算
28         printf("%lld\n", ans);
29     }
30     return 0;
31 }

 

posted @ 2016-01-23 17:32  小小泽  阅读(177)  评论(0编辑  收藏  举报