【Kickstart】2018 Round B - No Nine

解法

首先,把問題轉化成要求f[x],既小於等於x的合法數字的個數。這樣在FL之間的數就可以用f[F]-f[L]+1來得到了。

如果我們從0開始,用9進製表示整個自然數數列,我們可以得到:

0 1 2 …… 8 9 …… n
0 1 2 …… 8 10 …… m

觀察這個數列,我們可以發現第n+1個數,就是mmn的9進製表示。
在9進制數列裏,數字都是9個9個一組的,個位分別是0-8,十位及以後的位上有9的,就以組爲單位丟掉了,比如90-98910-918
而在這9個數裏,每個數mod 9的值都不同,總會有一個爲0,也就是說,每組裏只會有1個數是9的倍數

現在回到f[x]的求解,首先,我們設x=dndn1...d0=i=0ndi10ix=d_nd_{n-1}...d_0=\sum_{i=0}^n{d_i\cdot10^i}
由題目條件可知,它一定是個合法數字,所以它沒有9。
我們把它當成一個9進制的數,轉回十進制之後,得到y=i=0ndi9iy = \sum_{i=0}^n{d_i\cdot9^i},就能知道它是第y+1個數,但是這時候有個問題,y+1 = 9a+b包含了a個整組和b個單獨的數,容易知道b=(d0+1)%9b=(d_0+1)\%9,所以:

  1. 如果d0=8d_0=8,那麼剛好a整組
  2. 如果d0<8d_0< 8,那麼需要對這d0+1d_0+1個數單獨check一下是不是9的倍數
  • 爲了方便,可以直接把 [xd0,x][x-d_0,x] 都check一下,不用管d0d_0是不是等於8。
  • xd0x-d_0剛好是第yd0+1y-d_0+1個數,所以在它前面,也就是[0,xd0)[0,x-d_0)裏有yd0y-d_0個數,它應該剛好能分成i=1di9i1\sum_{i=1}d_i\cdot9^{i-1}個組,每個組8個合法數字
#!/usr/bin/env python
# -*- coding: utf-8 -*-

def find(x):
    ans = 0
    y = x-x%10
    for i in xrange(y,x+1):
        if i%9!=0:
            ans += 1

    y /= 10
    i = 0
    mid = 0
    while y>0:
        mid += (y%10)*9**i
        i += 1
        y /= 10
    mid = mid<<3
    return mid+ans

def solve(f,l):
    return find(l)-find(f)+1

if __name__ == '__main__':
    t = input()
    for round in xrange(1,t+1):
        print "Case #%d: %d" %(round,solve(*map(int, raw_input().split())))

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章