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 }