洗牌找规律java_HDU 4759 – Poker Shuffle [找规律+大数]

题意:给定2^N张扑克牌,重新洗几次牌后,问是否存在a位置上为x,b位置上为y的情况。每次洗牌的规则是原奇数位置扑克在前原偶数位置在后,或者原偶数位置扑克在前原奇数位置在后。

分析:这道题就是找规律,比赛的时候只关注了每个位置扑克牌的变化情况了,如果关注每张扑克牌的位置变化,就会发现两种规则都是有规律的。

将每张扑克牌的牌面-1,位置也-1,这样从0开始,更符合逻辑。如果洗牌时原奇数位置扑克在前原偶数位置在后,那么观察某张扑克的位置的二进制变化就知道,是右移一位左边异或1;反过来,是右移一位左边异或0.

那么好办了,如果是按照统一规则变化的扑克牌,两张扑克牌的变化i步必定都是右移i位再异或上同一个数。这样我们解这道题时可以模拟这样一个变化:初始时刻,x在位置x上,y在位置y上,同时右移i位并并异或上某个相同数后,的到了两个数的位置a和b(程序实现要参考异或性质反过来求这个数),那么说明这i步变化是相同的,即存在一种情况使得最后a位置上为x,b位置上为y。

(这次说的够清楚了,以前写博客写的好少,哈哈,得坚持这样写。)

Java代码:

import java.math.BigInteger;

import java.util.Scanner;

public class Main{

private static int N;

private static BigInteger a, b, x, y;

private static BigInteger shift(BigInteger t) {

BigInteger s = t.and(BigInteger.ONE);

return t.shiftRight(1).or(s.shiftLeft(N-1));

}

private static boolean Judge() {

for(int i = 0; i < N; ++i) {

x = shift(x); y = shift(y);

if(x.xor(a).equals(y.xor(b)))

return true;

}

return false;

}

public static void main(String[] args) {

Scanner cin = new Scanner(System.in);

int T = cin.nextInt(), kase = 0;

while((T--) > 0) {

N = cin.nextInt();

a = cin.nextBigInteger().subtract(BigInteger.ONE);

x = cin.nextBigInteger().subtract(BigInteger.ONE);

b = cin.nextBigInteger().subtract(BigInteger.ONE);

y = cin.nextBigInteger().subtract(BigInteger.ONE);

if(Judge()) System.out.println("Case " + (++kase) + ": Yes");

else System.out.println("Case " + (++kase) + ": No");

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值