hdu 4759 Poker Shuffle

 1 /**
 2 大意: 有1-K 张牌, 有两种洗牌方式,一种奇数在前,一种偶数在前。。
 3 问结果多次洗牌之后,是否可以到达这种状态; a位置是x , b位置是y
 4 若是输出yes, 否则输出no
 5 
 6 思路:  将其转化为二进制。。。
 7 ————————————————————————————————————————————————————————
 8 二进制的运用。
 9 题目给的牌编号是从一开始的,要先将其转成从0开始的。
10 一开始的编号是0~2^N-1,每次洗牌的过程如下:
11 第一种洗牌:将奇数放前面,偶数放后面。每个位置的数的变化相当于二进制数右移一位(相当于除以2),然后最高位异或1。
12 第二种洗牌:将偶数放前面,奇数放后面。每个位置的数的变化相当于二进制数右移一位(相当于除以2),然后最高位异或0。
13 这样就把位置为i的牌,经过一次洗牌后的位置算出来了。
14 例如:      牌:   0     1    2    3    4    5     6     7                       0     1      2     3      4      5     6     7 
15             位置:   0     1    2    3    4    5     6     7        变成          4     0      5     1      6      2     7     3
16          二进制: 000 001 010 011 100 101 110 111                   100  000  101  001  110  010  111  011
17 上面的是第一种洗牌方式,可以看出奇数在前,偶数在后。
18 下面是第一种洗牌的规律:
19 000(0) -> 100(4) -> 110(6) -> 111(7) -> 011(3) -> 001(1) -> 000(0)
20 001(1) -> 000(0) -> 100(4) -> 110(6) -> 111(7) -> 011(3) -> 001(1)
21 010(2) -> 101(5) -> 010(2) -> 101(5) -> 010(2) -> 101(5) -> 010(2)
22 011(3) -> 001(1) -> 000(0) -> 100(4) -> 110(6) -> 111(7) -> 011(3)
23 100(4) -> 110(6) -> 111(7) -> 011(3) -> 001(1) -> 000(0) -> 100(4)
24 101(5) -> 010(2) -> 101(5) -> 010(2) -> 101(5) -> 010(2) -> 101(5)
25 110(6) -> 111(7) -> 011(3) -> 001(1) -> 000(0) -> 100(4) -> 110(6)
26 111(7) -> 011(3) -> 001(1) -> 000(0) -> 100(4) -> 110(6) -> 111(7)
27 可以看出,经过若按同一种洗牌方式,经过2*n次洗牌后,牌堆会恢复到原来的序列。
28 但是题目有两种洗牌方式,是反过来的,所以只要经过n次洗牌后就会恢复原来的序列了。
29 也就是说对于一堆2^n的牌,最多只有n种不同的序列,也就是最多右移n位,超过n位就会重复了。
30  
31 经过若干次洗牌,可以看成是右移了k位,然后异或上一个数。
32 所以首先将A X B Y都减一,然后枚举X,Y右移k位以后,能不能同时异或上相同的数得到A,B。
33 由于a^b=c,可以得到a^c=b
34 解法总结如下:
35 从1到n枚举右移X,Y,每次判断X^A是否等于Y^B。
36 n比较大,要用大数。
37 用java大数来处理比较方便。
38 ——————————————————————————————————————————————————————————————
39 **/
40 import java.io.*;
41 import java.util.*;
42 import java.math.*;
43 
44 public class Main{
45         static int n;
46         // 为什么是循环右移???---->只考虑了偶在前奇在后
47         public static BigInteger right(BigInteger a){
48                BigInteger tmp = a.and(BigInteger .ONE );
49                return a.shiftRight(1).or(tmp.shiftLeft(n-1));
50               
51        }
52        
53         public static void main(String[] args) {
54                int i,t,k,flag;
55                BigInteger A,B,X,Y,a,b;
56               Scanner cin = new Scanner(System. in);
57               t = cin.nextInt();
58                for(i=1;i<=t;i++){
59                      
60                       n = cin.nextInt();
61                      A = cin.nextBigInteger();
62                      X = cin.nextBigInteger();
63                      B = cin.nextBigInteger();
64                      Y = cin.nextBigInteger();
65                       //System.out.println(A+" "+X+" "+ B+ " "+ Y);
66                      A = A.add( BigInteger.valueOf(-1));
67                      X = X.add( BigInteger.valueOf(-1));
68                      B = B.add( BigInteger.valueOf(-1));
69                      Y = Y.add( BigInteger.valueOf(-1));
70                       //System.out.println(A+" "+X+" "+ B+ " "+ Y+"-------------->");
71                      flag =0;
72                       for(k=1;k<=2*n;k++){
73                            
74                            X = right(X);
75                            Y = right(Y);
76                            a =    X.xor(A);
77                            b = Y.xor(B);
78                             if(a.equals(b)){
79                                   flag =1;
80                                    break;
81                            }
82                      }
83                       //System.out.println(flag+"************");
84                       if(flag==1)
85                            System. out.println("Case " +i+": Yes" );
86                       else
87                            System. out.println("Case " +i+": No" );
88               }
89        }
90 }
原文地址:https://www.cnblogs.com/Bang-cansee/p/3724058.html