这是一个很好的题目,来自2013长春网赛。

题目的意思是给你2^N张扑克牌,每次洗牌前分别把从下开始数为奇数和偶数的牌分别拿出来放在一堆,两堆可以任意一个放在上面。

现在问你是否存在一种情况使得经过若干次洗牌后,第A张牌的编号为x,且同时第B张牌的编号为y。(初始状态从低到顶编号从1递增)

题目的解法是用二进制来模拟洗牌的过程,然后发现洗牌的规律为右移+异或操作,然后就可以解决了。

但其实本题最最难以想到的是,题目给你的牌的编号是从1开始的,然而为了方便地使用二进制,我们需要从0开始编号。

首先对于每一个牌,我们都先把其编号减一,相当于从0开始编号,这样对于读入的四个数,我们都将其减一就可以了。

然后我们需要在洗牌的过程中找出洗牌的规律。

是这样的,首先我们把奇数牌和偶数拍分别放成两堆,这样原来i为奇数的牌在奇数堆中间的编号就变为了(i/2),同理编号i为偶数的牌在偶数牌堆中的编号也是(i/2)。

由于要考虑两种牌分别放在上面的情况,我们先考虑奇数的牌放在上面的情况。

假设我们把所有的牌现有的位置用一个二进制表示,如果奇数的牌放在上面,那么偶数牌的最终编号就是偶数牌在偶数堆中间的编号,而奇数牌的编号需要把最高位由0变为1。

细细想来,把这用规律表示,这个规律就是如果奇数牌放下上面,那么现在牌的标号就是原来编号循环右移了一位

好,下面讨论偶数牌放在上面的情况,其实是一样的,只是我们只在偶数牌的编号前面最高位由0变为1而已。

同样我们也用规律表示出来,那就是现在牌的编号为原来编号循环右移一位,并且改变最高位。

综合上面两种说法,如果是奇数牌放在上面,那么所有牌的编号就是循环右移一位,然后最高位异或0;如果是偶数牌放在上面,那么所有牌的编号就是循环右移一位,然后最高位异或1.

现在回到题目,如果x能够通过n次洗牌序号变为A,那么x一定右移了n位,并且每一个数位都与0或1做了异或操作

由于每次洗牌两张牌都是做的同一个运算,也就是说x牌异或了1,那么y牌也一定异或了1。

那么我们只要枚举到底洗了多少次牌,然后看看对于每一位,x到A,y到B能否通过异或同一个值得到,如果所有的位数都是通过异或同一个值得到的,那么显然就存在这样的一个方案;否则,那就不存在这样的方案了。

下面还剩下最后一个问题,那就是我们到底应该判断多少位数呢?

最多只要n位,因为右移超过n位的话就是一个循环了,右移不会改变数位之间的对应关系。

 

第一次做这种二进制的题目,感觉题目的思路挺难想到的,虽然最终还是在内牛满面中A掉此题,但是如果比赛的时候出了这种类似的题目,依然无法保证能够A出来啊。。  T_T

 #include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1111
using namespace std; int a[maxn],b[maxn],x[maxn],y[maxn],f[maxn],n,k;
char s[maxn];
bool ans; void input(int t[])
{
scanf("%s",s+);
int N=strlen(s+),cur=,tep;
memset(f,,sizeof f);
for (int i=; i<=N; i++) f[i]=s[N+-i]-'';
f[]--;
for (int i=; f[i]<; ) f[i]+=,f[++i]--;
while (N>=)
{
tep=;
t[++cur]=(f[]&);
for (int i=N; i>; i--)
{
f[i]+=*tep;
tep=(f[i]&);
f[i]>>=;
}
if (f[N]==) N--;
}
} int main()
{
int T;
scanf("%d",&T);
for (int cas=; cas<=T; cas++)
{
scanf("%d",&n);
memset(a,,sizeof a);
memset(x,,sizeof x);
memset(b,,sizeof b);
memset(y,,sizeof y);
input(a),input(x),input(b),input(y);
for (int i=; i<=n; i++)//右移了多少位
{
ans=true;
for (int j=; j<=n; j++)//当前第j位进行比较
{
k=j-i;//低位在前,所以右移相当于减
if (k<) k+=n;
if ((a[k]==x[j])^(b[k]==y[j]))
{
ans=false;
break;
}
}
if (ans) break;//找到了存在情况
}
printf("Case %d: ",cas);
if (ans) printf("Yes\n");
else printf("No\n");
}
return ;
}

HDU4759_Poker Shuffle的更多相关文章

  1. Spark Shuffle原理、Shuffle操作问题解决和参数调优

    摘要: 1 shuffle原理 1.1 mapreduce的shuffle原理 1.1.1 map task端操作 1.1.2 reduce task端操作 1.2 spark现在的SortShuff ...

  2. Collections.shuffle

    1.Collections.shuffler 最近有个需求是生成十万级至百万级的所有随机数,最简单的思路是一个个生成,生成新的时候排重,但是这样时间复杂度是o(n^2),网上看了几个博客的解决方法都不 ...

  3. [LeetCode] Shuffle an Array 数组洗牌

    Shuffle a set of numbers without duplicates. Example: // Init an array with set 1, 2, and 3. int[] n ...

  4. mapReduce的shuffle过程

    http://www.jianshu.com/p/c97ff0ab5f49 总结shuffle 过程: map端的shuffle: (1)map端产生数据,放入内存buffer中: (2)buffer ...

  5. spark shuffle 相关细节整理

    1.Shuffle Write 和Shuffle Read具体发生在哪里 2.哪里用到了Partitioner 3.何为mapSideCombine 4.何时进行排序 之前已经看过spark shuf ...

  6. Hadoop学习笔记—10.Shuffle过程那点事儿

    一.回顾Reduce阶段三大步骤 在第四篇博文<初识MapReduce>中,我们认识了MapReduce的八大步骤,其中在Reduce阶段总共三个步骤,如下图所示: 其中,Step2.1就 ...

  7. 由乱序播放说开了去-数组的打乱算法Fisher–Yates Shuffle

    之前用HTML5的Audio API写了个音乐频谱效果,再之后又加了个播放列表就成了个简单的播放器,其中弄了个功能是'Shuffle'也就是一般播放器都有的列表打乱功能,或者理解为随机播放. 但我觉得 ...

  8. 【面试】shuffle函数的实现

    一.前言 有位同学面试的时候被问到shuffle函数的实现,他之后问我,我知道这个函数怎么用,知道是对数组(或集合)中的元素按随机顺序重新排列.但是没有深入研究这个是怎么实现的.现在直接进入JDK源码 ...

  9. MapReduce Shuffle过程

    MapReduce Shuffle 过程详解 一.MapReduce Shuffle过程 1. Map Shuffle过程 2. Reduce Shuffle过程 二.Map Shuffle过程 1. ...

随机推荐

  1. 20155322 2017-2018-1《信息安全系统设计》第十周 课下作业-IPC

    20155322 2017-2018-1<信息安全系统设计>课下作业-IPC 作业内容 研究Linux下IPC机制:原理,优缺点,每种机制至少给一个示例,提交研究博客的链接. 共享内存 管 ...

  2. 20155328 2016-2017-2 《Java程序设计》 第一周学习总结

    20155328 2016-2017-2 <Java程序设计> 第一周学习总结 教材学习内容总结 本周学习目标是浏览<Java学习笔记>中的十八章,其中第一章和第二章认真学习, ...

  3. 20145226夏艺华 EXP5 MSF基础应用

    实践目标 · 掌握metasploit的基本应用方式. · 具体需要完成 (1)ms08_067; (2)ms11_050: (3)Adobe (4)成功应用任何一个辅助模块. 报告 本次实验一共用到 ...

  4. 【NOIP2018】提高组题解

    [NOIP2018]提高组题解 其实就是把写过的打个包而已 道路铺设 货币系统 赛道修建 旅行 咕咕咕 咕咕咕

  5. 4361: isn

    4361: isn https://lydsy.com/JudgeOnline/problem.php?id=4361 分析: dp+容斥. 首先计算出每个长度有多少种子序列是非降的.这一步可以$n^ ...

  6. 运行ntpdate报错:Temporary failure in name resolution

    一.问题报错: 忽然发现某台机器时间慢了些几分钟,之前没有搭建ntpd服务,目前都是使用的ntpdate加定时任务进行时间同步.直接执行ntpdate报错如下: # ntpdate cn.pool.n ...

  7. Linux系统运维基础管理命令总结

    1.查看系统负载命令:w.uptime [root@localhost ~]# w :: up days, :, user, load average: 0.00, 0.01, 0.05 USER T ...

  8. SaltStack入门篇(三)之数据系统Grains、Pillar

    1.什么是Grains? Grains是saltstack的组件,用于收集salt-minion在启动时候的信息,又称为静态信息.可以理解为Grains记录着每台Minion的一些常用属性,比如CPU ...

  9. Linux环境配置备忘

    1.Ubuntu服务器版本装scipy 预装版本可能fortran包版本过旧或者不全,安装scipy之前需要更新环境. sudo apt-get install gfortran libopenbla ...

  10. Mongodb大数据语法大全

    JSON和MONGODBJSON不止是一种交换数据的方式,也是一种存储数据的良好方式,实际上MONGODB并未使用JSON存储数据,而是使用由MONGODB团队开发的一种称为BSON的开放数据格式. ...