这是 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);
}
}
}