hdu 4759 - Poker Shuffle(巧妙二进制)

思路from:http://blog.csdn.net/cc_again/article/details/12174269

   下面先介绍一种运算:

   把xx右移一位的同时,把最后一位数字放到第一位上。

   例如 n = 3; 那么编号从0开始的话,

   0(000) -->0(000) -->0(000) -->0(000)

   1(001) -->4(100) -->2(010) -->1(001)

   2(010) -->1(001) -->4(100) -->2(010)

   3(011) -->5(101) -->6(110) -->3(011)

   4(100) -->2(010) -->1(001) -->4(100)

   5(101) -->6(110) -->3(011) -->5(101)

   6(110) -->3(011) -->5(101) -->6(110)

   7(111) -->7(111) -->7(111) -->7(111)

对于序数为偶数的牌,也就是最低位为0的牌,直接循环右移一位,相当于除以二,这样就凑出了第一堆,

对于序数为奇数的牌,最低位为1,循环右移一位后,相当于除二后加了2^(n-1),也就是加了前面偶数堆的长度。

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

对于抑或可以先移位然后所有位一起抑或,但是右移操作最多只有n次,超过n次的话,就重复了,所以可以先右移n次,每右移一次(切牌)有两种方式抑或0或者1,这样就得到了一个长度为n的o、1抑或串,也就是切牌方式。

枚举开始点,右移次数k,将X,Y右移K位,

由于a^b=c可以推出a^c=b,所以把X抑或A与Y抑或B比较,判断是否相同(相同表示序号为X的牌和序号为Y的牌可以经过相同的切牌方式得到位置A和B)。

代码如下:

import java.math.*;
import java.util.*;

public class Main
{
    static int n;
    static Scanner cin = new Scanner(System.in);
    static BigInteger rot(BigInteger x)
    {
        BigInteger s = x.and(BigInteger.valueOf(1));
        return x.shiftRight(1).or(s.shiftLeft(n-1));
    }
    public static void main(String[] args)
    {
        int t = cin.nextInt(), K = 0;
        while(++K<=t)
        {
            n = cin.nextInt();
            BigInteger A = cin.nextBigInteger(), X = cin.nextBigInteger();
            BigInteger B = cin.nextBigInteger(), Y = cin.nextBigInteger();
            A = A.add(BigInteger.valueOf(-1));
            B = B.add(BigInteger.valueOf(-1));
            X = X.add(BigInteger.valueOf(-1));
            Y = Y.add(BigInteger.valueOf(-1));
            String ans = "No";

            for(int i = 0; i <= n; ++i)
            {
                A = rot(A);
                B = rot(B);
                BigInteger dx = A.xor(X);
                BigInteger dy = B.xor(Y);
                if(dx.compareTo(dy) == 0)
                {
                    ans = "Yes";
                    break;
                }
            }
            System.out.println("Case "+ K + ": " + ans);
        }
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值