题意

https://www.cometoj.com/contest/35/problem/C?problem_id=1498

思路

这题要用到一种比较小众的状压方法(没见过的话可能一时比较难想到)。

首先观察题面,发现可以把一个人有另一个人没有的点数都视作同一种(转化一),然后点数之间也可以任意转化(转化二),不影响结果,经过如上转化,可以将任意情况转化为两方各有一些相同点数的手牌,然后不同点数的手牌只有一种或没有。

(感觉说的好乱啊,举个栗子吧...

\[\begin{array}{}
&2,3,5,6,6|1,2,5,5,7\\
\to&2,5,X,X,X|2,5,5,Y,Y\text{(转化一)}\\
\to&1,2,X,X,X|1,2,2,Y,Y\text{(转化二)}\\
\to&1,2,3,3,3|1,2,2,4,4\text{(转化二)}\\
\end{array}
\]

然后就是状压的部分,由于两人最多只能有 \(8\) 张手牌。而手牌之间只有相同不相同才有影响,于是把手牌变成 \(01\) 序列,即相邻不同的用 \(01\) 相区别。

(感觉还是不清楚啊,继续举栗子吧...

\(1,2,3,3,3 \to 10111\)

$ 1,2,2,4,4 \to 10011$

当然为了表示有没有对方没有对牌,还需另外记一个布尔值。

最后,任何时刻不得打出上次打出的牌,所以再记一个整数表示上一次打出的手牌标号,为了方便起见,这个标号是相对于本方而言的。然后如果因为是第一回合,或者对方打了本方没有的牌等情况,没有这个限制的话,这个整数就记为 \(8\) (因为本方手牌最多从 \(0\) 标号到 \(7\) 嘛)。

细节还是很多的,据说出题人和验题人的代码也都很长,我还是赛后膜改一天改出了下面这个代码,感触最深的就是把位操作封函数后会好写很多。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
int dp[(1<<8)+5][2][(1<<8)+5][2][9]; //0:lose 1:draw 2:win
int bin[(1<<8)+5]; //dp[a][b][c][d][e]
int T; //a为本方手牌
//b为本方有没有对方没有的牌
inline int bit_take(int B,int l,int r) //c为对方手牌
{ //d为对方有没有本方没有的牌
return B&(((1<<(r+1))-1)^((1<<l)-1)); //e为上一次出的手牌标号(相对本方而言)
}
inline int bit_erase(int B,int x)
{
return bit_take(B,0,x-1)|(bit_take(B,x+1,bin[B])>>1);
}
inline int bit_reverse(int B,int l,int r)
{
return B^(((1<<(r+1))-1)^((1<<l)-1));
}
inline int bit_swapping(int B,int l1,int r1,int r2)
{
int B1=bit_take(B,l1,r1),B2=bit_take(B,r1+1,r2);
return (B^B1^B2)|(B1<<(r2-r1))|(B2>>(r1-l1+1));
} int get_dp(int A,bool a,int B,int b,int las)
{
int &res=dp[A][a][B][b][las];
if(~res)return res;
else if(B==0)
{
if(las==8)return res=1;
else return res=0;
}
res=0;
int cnta=-1,cntb=-1;
int ra[9],rb[9];
DOR(i,bin[A],0)if(i==bin[A]||((A>>i&1)!=(A>>(i+1)&1)))ra[++cnta]=i;
DOR(i,bin[B],0)if(i==bin[B]||((B>>i&1)!=(B>>(i+1)&1)))rb[++cntb]=i;
ra[cnta+1]=rb[cntb+1]=-1;
FOR(i,0,cnta)
{
int l=ra[i+1]+1,r=ra[i];
if(i!=las)
{
int nA=bit_erase(A,r),na=a,nB=B,nb=b,nlas;
if(l==r)
{
nA=bit_reverse(nA,0,r-1);
if(a&&i==cnta)na=0,nlas=8;
else if(i==cntb)nb=1,nlas=cntb;
else
{
int x=rb[cntb+1]+1,y=rb[i+1],z=rb[i];
nB=bit_reverse(nB,x,y);
if((cntb-b-i)&1)nB=bit_reverse(nB,y+1,z);
nB=bit_swapping(nB,x,y,z);
if(b)nlas=8;
else nlas=cntb,nb=1;
}
}
else
{
if(a&&i==cnta)nlas=8;
else nlas=i;
}
chk_max(res,2-get_dp(nB,nb,nA,na,nlas));
}
}
return res;
} void solve()
{
int n;
int A[25]={0},B[25]={0};
scanf("%d",&n);
FOR(i,1,n)
{
int x;
scanf("%d",&x);
A[x]++;
}
FOR(i,1,n)
{
int x;
scanf("%d",&x);
B[x]++;
}
int X=0,Y=0,x=0,y=0;
bool cur=1;
FOR(i,1,20)
{
if(A[i]&&!B[i])x+=A[i];
else if(!A[i]&&B[i])y+=B[i];
else if(A[i]&&B[i])
{
FOR(j,1,A[i])X=(X<<1)|cur;
FOR(j,1,B[i])Y=(Y<<1)|cur;
cur^=1;
}
}
FOR(i,1,x)X=(X<<1)|cur;
FOR(i,1,y)Y=(Y<<1)|cur; //转化手牌
int res=get_dp(X,x!=0,Y,y!=0,8);
if(res==0)puts("dreamoon wins");
else if(res==1)puts("Draw");
else if(res==2)puts("AA wins");
} int main()
{
bin[1]=0;FOR(i,2,1<<8)bin[i]=bin[i>>1]+1;
memset(dp,-1,sizeof(dp));
int T;
scanf("%d",&T);
while(T--)solve();
return 0;
}

Comet OJ - Contest #1 C 复读游戏(状态压缩)的更多相关文章

  1. Comet OJ - Contest #8

    Comet OJ - Contest #8 传送门 A.杀手皇后 签到. Code #include <bits/stdc++.h> using namespace std; typede ...

  2. Comet OJ - Contest #2 简要题解

    Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...

  3. Comet OJ - Contest #2简要题解

    Comet OJ - Contest #2简要题解 前言: 我没有小裙子,我太菜了. A 因自过去而至的残响起舞 https://www.cometoj.com/contest/37/problem/ ...

  4. Comet OJ - Contest #4--前缀和

    原题:Comet OJ - Contest #4-B https://www.cometoj.com/contest/39/problem/B?problem_id=1577传送门 一开始就想着暴力打 ...

  5. Comet OJ - Contest #11 题解&赛后总结

    Solution of Comet OJ - Contest #11 A.eon -Problem designed by Starria- 在模 10 意义下,答案变为最大数的最低位(即原数数位的最 ...

  6. Comet OJ - Contest #13-C2

    Comet OJ - Contest #13-C2 C2-佛御石之钵 -不碎的意志-」(困难版) 又是一道并查集.最近做过的并查集的题貌似蛮多的. 思路 首先考虑,每次处理矩形只考虑从0变成1的点.这 ...

  7. Comet OJ - Contest #13 「火鼠的皮衣 -不焦躁的内心-」

    来源:Comet OJ - Contest #13 芝士相关: 复平面在信息学奥赛中的应用[雾 其实是道 sb 题??? 发现原式貌似十分可二项式定理,然后发现确实如此 我们把 \(a^i\) 替换成 ...

  8. Comet OJ - Contest #13 「佛御石之钵 -不碎的意志-」(hard)

    来源:Comet OJ - Contest #13 一眼并查集,然后发现这题 tmd 要卡常数的说卧槽... 发现这里又要用并查集跳过访问点,又要用并查集维护联通块,于是开俩并查集分别维护就好了 一开 ...

  9. Comet OJ - Contest #5

    Comet OJ - Contest #5 总有一天,我会拿掉给\(dyj\)的小裙子的. A 显然 \(ans = min(cnt_1/3,cnt_4/2,cnt5)\) B 我们可以感性理解一下, ...

随机推荐

  1. web应急:新闻源网站劫持

    新闻源网站一般权重较高,收录快,能够被搜索引擎优先收录,是黑灰产推广引流的必争之地,很容易成为被攻击的对象.被黑以后主要挂的不良信息内容主要是博彩六合彩等赌博类内容,新闻源网站程序无论是自主开发的还是 ...

  2. golang学习笔记---string && strconv

    1.字符串的组成?Golang的字符串都是由单个字节连接起来的,每个字节都是UTF8编码标识的Unicode文本.(不需要在考虑中文不兼容问题) 2.如何遍历字符串?先看一个例子: package m ...

  3. .net架构的浅谈

    ,net的架构有以下几种 1.两层架构:UI + 数据层 2.三层架构:UI + 业务层 + 数据层 3.三层 + 接口层 (把相关的业务层抽象成接口,下层来实现接口,中层是依赖) 4.三层 + 接口 ...

  4. virtualbox通过Nat模式上网,宿主机与宿主机互通

    本地搭建virtualbox,开始用的nat转发模式,这样的话宿主机没法访问虚拟机里面的服务.比如nginx网站.这样很不方便 . 在网上找了好久,终于找到了方案.那就是再添加一块虚拟网卡. 在虚拟机 ...

  5. 关于 Java 关键字 volatile 的总结

    1 什么是 volatile volatile 是 Java 的一个关键字,它提供了一种轻量级的同步机制.相比于重量级锁 synchronized,volatile 更为轻量级,因为它不会引起线程上下 ...

  6. Docker容器进入的4种方式以及tomcat查看日志

    docker logs 查看实时日志 原文:http://www.cnblogs.com/qufanblog/p/6927411.html docker logs -f -t --since=&quo ...

  7. 利用selenium和ffmpeg爬取m3u8 ts视频《进击的巨人》

    需求 想看下动漫<进击的巨人>,发现到处被和谐,找不到资源,但是在一个视频网站找到了在线播放,https://www.55cc.cc/dongman/17890/player-2-1.ht ...

  8. oracle查看表空间的真实使用情况

    --查看表空间的真实使用情况 set linesize 500 pagesize 500 col tablespace_name format a25 col TP_REAL_GB format a1 ...

  9. 微信小程序到底把什么定义为风险内容?

    目录 起因 经过和结果 附录: 起因 之前做一个群相册的小程序,因为涉及到图片和评论等内容的发布分享.因此,微信后台要求有一定的内容安全检测能力. 但是,我用别家的内容检测用的好好的,在国庆前被微信警 ...

  10. idea 2019 集成activiti, idea activiti 新建bpmn文件, 解决idea activiti中文乱码

    idea 在线安装activiti插件 1. File-->Settings 2. 点击Plugins, 右侧界面点击Marketplace后在搜索框搜索 actiBPM 注: 网络原因没有加载 ...