zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    gbk与utf-8转换
    gdb注意事项
    Ubuntu导入证书
    Ubuntu 修改hosts
    GDB配置与.gdbinit的编写
    linux中用户的主目录~
    关于C++构造函数初始化顺序
    C++中的static关键字的总结
    Flutter移动电商实战 --(2)建立项目和编写入口文件
    Flutter移动电商实战 --(1)项目学习记录
  • 原文地址:https://www.cnblogs.com/Bang-cansee/p/3724058.html
Copyright © 2011-2022 走看看