zoukankan      html  css  js  c++  java
  • 2013长春网赛1001 hdu 4759 Poker Shuffle

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4759

    题意:有一堆2^n的牌,牌原先按(1,2,....k)排序,每一次洗牌都将牌分成两种情况:(1,3,5,....k-1)或(2,4,6,.....k),

    给出四个数:A  X  B  Y  ,问有没有可能出现A位置的牌序号为X,B位置的牌序号是Y。输出Yes或No。

    1 <= N <= 1000, 1 <= A, B, X, Y <= 2^N.

    分析:二进制的运用。

    题目给的牌编号是从一开始的,要先将其转成从0开始的。

    一开始的编号是0~2^N-1,每次洗牌的过程如下:

    第一种洗牌:将奇数放前面,偶数放后面。每个位置的数的变化相当于二进制数右移一位(相当于除以2),然后最高位异或1。

    第二种洗牌:将偶数放前面,奇数放后面。每个位置的数的变化相当于二进制数右移一位(相当于除以2),然后最高位异或0。

    这样就把位置为i的牌,经过一次洗牌后的位置算出来了。

    例如:      牌:   0     1    2    3    4    5     6     7                       0     1      2     3      4      5     6     7 

                位置:   0     1    2    3    4    5     6     7        变成          4     0      5     1      6      2     7     3

             二进制: 000 001 010 011 100 101 110 111                   100  000  101  001  110  010  111  011

    上面的是第一种洗牌方式,可以看出奇数在前,偶数在后。

    下面是第一种洗牌的规律:

    000(0) -> 100(4) -> 110(6) -> 111(7) -> 011(3) -> 001(1) -> 000(0)

    001(1) -> 000(0) -> 100(4) -> 110(6) -> 111(7) -> 011(3) -> 001(1)

    010(2) -> 101(5) -> 010(2) -> 101(5) -> 010(2) -> 101(5) -> 010(2)

    011(3) -> 001(1) -> 000(0) -> 100(4) -> 110(6) -> 111(7) -> 011(3)

    100(4) -> 110(6) -> 111(7) -> 011(3) -> 001(1) -> 000(0) -> 100(4)

    101(5) -> 010(2) -> 101(5) -> 010(2) -> 101(5) -> 010(2) -> 101(5)

    110(6) -> 111(7) -> 011(3) -> 001(1) -> 000(0) -> 100(4) -> 110(6)

    111(7) -> 011(3) -> 001(1) -> 000(0) -> 100(4) -> 110(6) -> 111(7)

    可以看出,经过若按同一种洗牌方式,经过2*n次洗牌后,牌堆会恢复到原来的序列。

    但是题目有两种洗牌方式,是反过来的,所以只要经过n次洗牌后就会恢复原来的序列了。

    也就是说对于一堆2^n的牌,最多只有n种不同的序列,也就是最多右移n位,超过n位就会重复了。

    经过若干次洗牌,可以看成是右移了k位,然后异或上一个数。

    所以首先将A X B Y都减一,然后枚举X,Y右移k位以后,能不能同时异或上相同的数得到A,B。

    由于a^b=c,可以得到a^c=b

    解法总结如下:

    从1到n枚举右移X,Y,每次判断X^A是否等于Y^B。

    n比较大,要用大数。

    用java大数来处理比较方便。

    AC 代码:

     1 import java.io.*;
     2 import java.util.*;
     3 import java.math.*;
     4 public class Main {
     5     static int n;
     6     public static BigInteger right(BigInteger a)     //循环移位
     7     {
     8         BigInteger tmp=a.and(BigInteger.ONE);       //取出最低位作为右移后的首位
     9         return a.shiftRight(1).or(tmp.shiftLeft(n-1));    //将最低位加到最高位上
    10     }
    11     public static void main(String[] args) {
    12         int i,t,k,flag;
    13         BigInteger A,B,X,Y,a,b;
    14         Scanner cin=new Scanner(System.in);
    15         t=cin.nextInt();
    16         for(i=1;i<=t;i++)
    17         {
    18             n=cin.nextInt();
    19             A=cin.nextBigInteger();
    20             X=cin.nextBigInteger();
    21             B=cin.nextBigInteger();
    22             Y=cin.nextBigInteger();
    23             
    24             A=A.add(BigInteger.valueOf(-1));   //从0开始
    25             X=X.add(BigInteger.valueOf(-1));
    26             B=B.add(BigInteger.valueOf(-1));
    27             Y=Y.add(BigInteger.valueOf(-1));
    28             
    29             flag=0;
    30             for(k=1;k<=n;k++)
    31             {
    32                 X=right(X);
    33                 Y=right(Y);
    34                 a=X.xor(A);
    35                 b=Y.xor(B);
    36                 if(a.equals(b))
    37                 {
    38                     flag=1;
    39                     break;
    40                 }
    41             }
    42             if(flag==1)
    43                 System.out.println("Case "+i+": Yes");
    44             else
    45                 System.out.println("Case "+i+": No");
    46         }
    47     }
    48 
    49 }
    View Code
  • 相关阅读:
    CentOS 8.0配置阿里云yum源和epel源
    CentOS8 安装epel 使用阿里云镜像
    centos下yum使用proxy代理方法
    MySQL中的事务控制(一)start transaction
    MySQL中的锁定语句: lock tables 和 unlock tables
    MySQL中的触发器
    MySQL中的事件调度器
    MySQL中的流程控制
    MySQL中的不可见索引、倒序索引
    IDEA出现Push to origin/master was rejected
  • 原文地址:https://www.cnblogs.com/frog112111/p/3349816.html
Copyright © 2011-2022 走看看