#46370: 不用模擬,直接計算答案的數學角度解法


harlivy_forever (噴火水雞肉飯)

學校 : 國立嘉義高級中學
編號 : 160563
來源 : [163.27.3.96]
最後登入時間 :
2025-08-20 10:44:16

好像沒有看到跟我一樣的思路,所以想說分享一下。

 

提示一:不覺得左右左右切換的特性很像數位電路裡面的 counter 嗎?(好抱歉我在說屁話)

提示二:二進位

提示三:走到一個節點的路線跟該節點編號的二進位的關係

 

每層最右邊的節點編號都是 2 的某次方減 1,這棵樹看起來就十分的二進位。觀察可以發現每個節點的編號轉為二進位後,都可以是「走到這個節點」的路程紀錄。舉例來說,810 = 10002,要走到 8 的路程是「左左左」;1010 = 10102,走到 10 的路程是「左右左」。一個深度為 n 的節點的編號換成二進位會有 n 位,第一未必為 1,後面的 n-1 位數若是 0 則代表左,1 則代表右。說得更清楚點,000 代表左左左,010 代表左右左,001 代表左左右……

 

把深度為 4 時落到的葉節點列出來說明,第___位代表的是該球最終落到的葉節點編號轉換為二進制後的位數。從這裡開始就不用管什麼左右跟什麼樹了,只要專注在數字的規律就好。

第幾顆球第 4 位第 3 位第 2 位第 1 位
11000
21100
31010
41110
51001
61101
71011

 

發現規律了嗎?從上往下看,第 4 位永遠不變,第 3 位每 2 顆球為一循環切換 (0, 1, 0, 1,...,01 是一個循環),第 2 位每 4 顆球為一循環切換(0, 0, 1, 1, 0, 0, 1, 1, 0...,0011 是一個循環),第 1 位每 8顆球為一循環切換(00001111 是一個循環)。只要知道現在在一個循環的前半部還是後半部,我們就可以知道這顆球抵達的葉節點編號轉為二進位後在這個位數是 0 還是 1。我們怎麼得知現在在一個循環的前半部還是後半部?既然變化規律是以幾顆球幾顆球為一循環,只要知道這是第幾顆球就可以了!

 

若在某位數的規律是每 n 個球一循環,則球的編號對 n 的餘數是 1~(n/2) 時,該位數為 0,否則為 1。以第 7 顆球為例,第 4 位永遠是 1。7 % 2 = 1,是循環前半部,所以第 3 位是 0。7 % 4 = 3,是循環後半部(7 % 4 > 4 / 2 = 2),所以第 2 位是 1。7 % 8 = 7,是循環後半部(7 % 8 > 8 / 2 = 4),所以第 1 位是 1。第 7 顆球落到的葉節點編號便是 10112 = 1110

 

可能說得不夠清楚,最後是一點小補充:二進制每位的循環長度是 1, 2, 4, 8,... 在變動的,深度為 D 的樹的葉節點二進制編號第 n 位的循環長度是 2D-n

#46371: Re: 不用模擬,直接計算答案的數學角度解法


harlivy_forever (噴火水雞肉飯)

學校 : 國立嘉義高級中學
編號 : 160563
來源 : [163.27.3.96]
最後登入時間 :
2025-08-20 10:44:16

好像沒有看到跟我一樣的思路,所以想說分享一下。

 

提示一:不覺得左右左右切換的特性很像數位電路裡面的 counter 嗎?(好抱歉我在說屁話)

提示二:二進位

提示三:走到一個節點的路線跟該節點編號的二進位的關係

 

每層最右邊的節點編號都是 2 的某次方減 1,這棵樹看起來就十分的二進位。觀察可以發現每個節點的編號轉為二進位後,都可以是「走到這個節點」的路程紀錄。舉例來說,810 = 10002,要走到 8 的路程是「左左左」;1010 = 10102,走到 10 的路程是「左右左」。一個深度為 n 的節點的編號換成二進位會有 n 位,第一位必為 1,後面的 n-1 位數若是 0 則代表左,1 則代表右。說得更清楚點,000 代表左左左,010 代表左右左,001 代表左左右……

 

把深度為 4 時落到的葉節點列出來說明,第___位代表的是該球最終落到的葉節點編號轉換為二進制後的位數。從這裡開始就不用管什麼左右跟什麼樹了,只要專注在數字的規律就好。

第幾顆球第 4 位第 3 位第 2 位第 1 位
11000
21100
31010
41110
51001
61101
71011

 

發現規律了嗎?從上往下看,第 4 位永遠不變,第 3 位每 2 顆球為一循環切換 (0, 1, 0, 1,...,01 是一個循環),第 2 位每 4 顆球為一循環切換(0, 0, 1, 1, 0, 0, 1, 1, 0...,0011 是一個循環),第 1 位每 8顆球為一循環切換(00001111 是一個循環)。只要知道現在在一個循環的前半部還是後半部,我們就可以知道這顆球抵達的葉節點編號轉為二進位後在這個位數是 0 還是 1。我們怎麼得知現在在一個循環的前半部還是後半部?既然變化規律是以幾顆球幾顆球為一循環,只要知道這是第幾顆球就可以了!

 

若在某位數的規律是每 n 個球一循環,則球的編號對 n 的餘數是 1~(n/2) 時,該位數為 0,否則為 1。以第 7 顆球為例,第 4 位永遠是 1。7 % 2 = 1,是循環前半部,所以第 3 位是 0。7 % 4 = 3,是循環後半部(7 % 4 > 4 / 2 = 2),所以第 2 位是 1。7 % 8 = 7,是循環後半部(7 % 8 > 8 / 2 = 4),所以第 1 位是 1。第 7 顆球落到的葉節點編號便是 10112 = 1110

 

可能說得不夠清楚,最後是一點小補充:二進制每位的循環長度是 1, 2, 4, 8,... 在變動的,深度為 D 的樹的葉節點二進制編號第 n 位的循環長度是 2D-n

int main()
{

    int power[21], temp = 1;
    for(int i = 0; i <= 20; i++)
    {
        power[i] = temp;
        temp *= 2;
    }

    int T, D, I;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d", &D, &I);
        int ans = 0;
        for(int i = D - 1; i >= 0; i--)
            if(!(I % power[D - 1 - i]) || I % power[D - 1 - i] > power[D - 1 - i] / 2)
                ans += power[i];
        printf("%d\n", ans);
    }
}