這是 meelo 原創的 IEEEXtreme極限編程比賽題解
題目來源 第10屆IEEE極限編程大賽
https://www.hackerrank.com/contests/ieeextreme-challenges/challenges/flower-games
Joy and her friends found a flower with N petals and want to play a modified version of the He loves me... he loves me not game. The girls number the petals with numbers from 1 to N in the clockwise direction. They will traverse the petals in circular order starting with 1, then 2, ..., then N, then 1... At the first petal, they will shout "He loves me", at the second "He loves me not" and tear it, at the third "He loves me", at the fourth "He loves me not" and tear it. The girls will continue the game until there is only one petal left. The task is to identify the number of the last petal.
Input Format
The input begins with an integer T, giving the number of test cases in the input.
Each testcase consists of an integer N, on a line by itself.
Constraints
1 <= T <= 100000
1 <= N < 2^63
Output Format
The location of the last petal, on a line by itself.
Sample Input
4
2
3
4
6
Sample Output
1
3
1
5
Explanation
There are four test cases in the input.
With 2 petals, one would skip 1, tear 2, and then only 1 is left.
With 3 petals, one would skip 1, tear 2, skip 3, tear 1, and then only 3 is left.
With 4 petals, one would skip 1, tear 2, skip 3, tear 4, skip 1, tear 3, and then only 1 is left.
With 6 petals, one would skip 1, tear 2, skip 3, tear 4, skip 5, tear 6, skip 1, tear 3, skip 5, tear 1, and then only 5 is left.
題目解析
這題是約瑟夫環問題。由於N的大小是2^63,肯定不能使用模擬的方法。
在這個問題里跳躍的距離總是1,是一種最為特殊的情況,我們不妨來找找規律。
2片花瓣,留下的是1號
3片花瓣,留下的是3號
4片花瓣,留下的是1號
5片花瓣,留下的是3號
6片花瓣,留下的是5號
7片花瓣,留下的是7號
8片花瓣,留下的是1號
9片花瓣,留下的是3號
10片花瓣,留下的是5號
很有規律是吧,結果總是個奇數。表示成二進制數,去掉最后1為就是:0,1,0,1,2,3,0,1,2,3,4,5,6,7。如果再在二進制數的第一位補上1,就變成了2,3,4,5,6,7,8,9,10,11,12,13,14,15。
問題就解決了。
其實這個問題可以給出證明。
由於2片花瓣,留下的是1號。
那么3片花瓣,去掉1瓣后,就變成了一個2片花瓣的問題,我們知道這個新問題留下的是1號。那么這個新問題的1號是原來的多少號呢,2x1+1=3號。
那么4片花瓣,去掉2瓣后,就變成了一個2片花瓣的問題,我們知道這個新問題留下的是1號。那么這個新問題的1號是原來的多少號呢,(2x2+1)%4=1號。
那么5片花瓣,去掉1瓣后,就變成了一個4片花瓣的問題,我們知道這個新問題留下的是1號。那么這個新問題的1號是原來的多少號呢,2x1+1=3號。
有2個冪片花瓣,最終留下的就是1號。
問題一般化后,N=(b1b2b3...bn)二進制,去掉(b2b3...bn)2后,就變成了一個(b100...0)片花瓣的問題,我們知道這個新問題留下的是1號。那么這個新問題的1號是原來的多少號呢,2x(b2b3...bn)2+1號。
程序
Java
import java.io.*; import java.util.*; public class Solution { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int N = scan.nextInt(); for(int n = 0; n < N; n++) { long input = scan.nextLong(); long highest = Long.highestOneBit(input); long output = ((input & ~highest) << 1) + 1; System.out.println(output); } } }