新Nim游戏

因为第一次操作与其它操作不同,考虑拿出来单独做,剩下的操作就变成了 Nim游戏 了。

回忆一下 Nim游戏 先手必胜的条件是什么,是所有数的异或和不为 \(0\),那么这题就转化为求原集合的一个子集,该集合中的数不能被集合中的其它数的异或和表示,且集合内的数的和要尽量大。

首先这题输出 \(-1\) 显然没分,因为先手可以只留下一堆,后手的第一次操作就只能什么都不取,剩下的异或和不为 \(0\) ,先手必胜。然后我们看到异或和最大,想到线性基。一个数如果可以插入线性基,那就插入,如果不可以插入,则说明该数可以被线性基里的数的异或和表示,抛弃该数。那么现在就只剩下怎么取数了。想到若一个线性基可以被两个数插入,插入大的数必不劣于插入小的数,所以从大到小试插入即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=110;
int n,a[N],p[40];
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n);
for(int i=1;i<=n;i++){
read(a[i]);
}
sort(a+1,a+n+1);
int ans=0;
for(int i=n;i;i--){
int x=a[i];
for(int j=30;j>=0;j--){
if(x>>j&1){
if(!p[j]){
p[j]=x;
break;
}
else{
x^=p[j];
}
}
}
if(!x){
ans+=a[i];
}
}
write_endl(ans);
return 0;
}

[CQOI2013]棋盘游戏

可以发现白棋能赢当且仅当两个棋子初始距离为 \(1\),否则白棋必输。

那么问题只剩下黑棋最少需要几步才能吃掉白棋。可以发现最多需要 \(3n\) 步,要求出准确答案,这里涉及一个叫做对抗搜索的博弈论问题。

对抗搜索

定义:竞争环境中多个玩家之间的目标是有冲突的,称为对抗搜索问题。

特点:

  1. 确定的、完全可查的环境。
  2. 智能体轮流行动。
  3. 零和博弈
  4. 每一步行动的结果确定

这题中先手的目的是尽量拖时间,后手的目的是尽快结束游戏,所以搜索时记录操作人,操作步数,位置状态,然后每次操作按照两者的目的操作即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int inf=1e9;
int n,r1,c1,r2,c2,f[2][62][21][21][21][21],dx[2][8],dy[2][8];
int dfs(int opt,int step,int r1,int c1,int r2,int c2){
if(step>n*3){
return inf;
}
if(f[opt][step][r1][c1][r2][c2]&&f[opt][step][r1][c1][r2][c2]!=inf){
return f[opt][step][r1][c1][r2][c2];
}
if(r1==r2&&c1==c2){
if(opt)return inf;
return 0;
}
int ans;
if(opt==0){
ans=0;
for(int i=0;i<4;i++){
int x=r1+dx[0][i],y=c1+dy[0][i];
if(x>n||x<1||y>n||y<1){
continue;
}
ans=max(dfs(1,step+1,x,y,r2,c2),ans);
}
}
else{
ans=inf;
for(int i=0;i<8;i++){
int x=r2+dx[1][i],y=c2+dy[1][i];
if(x>n||x<1||y>n||y<1){
continue;
}
ans=min(dfs(0,step+1,r1,c1,x,y),ans);
}
}
return (f[opt][step][r1][c1][r2][c2]=ans+1);
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
dx[0][0]=1,dy[0][1]=1,dx[0][2]=-1,dy[0][3]=-1;
dx[1][0]=1,dx[1][1]=2,dy[1][2]=1,dy[1][3]=2,dx[1][4]=-1,dx[1][5]=-2,dy[1][6]=-1,dy[1][7]=-2;
read(n),read(r1),read(c1),read(r2),read(c2);
if(abs(r1-r2)+abs(c1-c2)==1){
puts("WHITE 1");
return 0;
}
printf("BLACK %d",dfs(0,0,r1,c1,r2,c2));
return 0;
}

图的逆变换

发现一个性质,如果两个点有相同的出点那么两个点的出点集合必然相同,考虑用种类并查集维护两个点是否有相同的出点,如果从 \(u\) 到 \(v\) 有边,将 \(u+n\) 和 \(v\) 分到一类。最后 \(O(n^2)\) 扫一遍,若存在 \(i+n\) 和 \(j\) 属于同一类,且 \(i\) 没有到 \(j\) 的边,输出 No;否则输出 Yes

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=310,base=1145141;
int n,m,fa[N<<1],e[N][N];
int getfa(int x){
if(fa[x]!=x){
fa[x]=getfa(fa[x]);
}
return fa[x];
}
void solve(){
read(n),read(m);
for(int i=1;i<=n*2;i++){
fa[i]=i;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
e[i][j]=0;
}
}
for(int i=1;i<=m;i++){
int u,v;
read(u),read(v);
u++,v++;
e[u][v]=1;
if(getfa(u+n)!=getfa(v)){
fa[getfa(u+n)]=getfa(v);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(getfa(i+n)==getfa(j)&&!e[i][j]){
puts("No");
return;
}
}
}
puts("Yes");
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
int t;
read(t);
while(t--){
solve();
}
return 0;
}

二进制A+B

本题有两种做法,这里使用的是构造。

先考虑无解情况:若 \(c=0,a\not=0\text{或}b\not=0\),显然无解;若 \(\operatorname{popcount}(c)>\operatorname{popcount}(a)+\operatorname{popcount}(b)\),也是无解;令 \(len\) 为原来的基准位数,若答案在二进制下的位数大于 \(len\),无解;其它情况均为有解。

令 \(\operatorname{popcount}(a)\ge\operatorname{popcount}(b)\),对于有解的考虑分类讨论

  1. 若 \(\operatorname{popcount}(c)\le \operatorname{popcount}(b)\)

    类似于下面情况
00111111
01000011
10000010

因为 \(c\) 中 \(1\) 的个数少于 \(b\) 中 \(1\) 的个数,所以要删去一些 \(b\) 中的 \(1\),将要删去的 \(1\) 放在高位即可。

2. 若 \(\operatorname{popcount}(c)\le \operatorname{popcount}(a)\)

类似于下面情况

0111111
0011100
1011011

因为 \(c\) 中 \(1\) 的个数少于 \(a\) 中 \(1\) 的个数,所以要删去一些 \(a\) 中的 \(1\),将要删去的 \(1\) 放在高位即可。

3. 若 \(\operatorname{popcount}(c)\le \operatorname{popcount}(a)+\operatorname{popcount(b)}\)

类似于以下情况

011111100
011100011
111011111

考虑到 $\operatorname{popcount}(c)= \operatorname{popcount}(a)+\operatorname{popcount(b)} 时肯定是两个串前后拼起来,现在位数少了,选择消掉一些位数,可以发现两个长度为 \(l\) 的全 \(1\) 串加起来会消掉 \(l\) 位。设少了 \(cnt\) 位,将两个数前 \(cnt\) 位设为 \(1\),剩下的全部以不重复占位的方式放在后面。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
int a,b,c,ans;
int Count(int x){
int cnt=0;
while(x){
cnt+=(x&1ll);
x>>=1ll;
}
return cnt;
}
int get_len(int x){
int cnt=0;
while(x){
cnt++;
x>>=1ll;
}
return cnt;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(a),read(b),read(c);
int cnta=Count(a),cntb=Count(b),cntc=Count(c),len=max(get_len(a),max(get_len(b),get_len(c))),ans;
if(cnta<cntb){
swap(cnta,cntb);
}
if(!c&&(a||b)){
ans=-1;
}
else if(cntc<=cntb){
ans=(1<<cntc)-2+(1<<(cnta+cntb-cntc));
}
else if(cntc<=cnta){
ans=(1<<cnta)+(1<<cntc)-1-(1<<(cntc-cntb));
}
else if(cntc<=cnta+cntb){
int cnt=cnta+cntb-cntc;
cnt=cntc-cnt;
ans=(1<<(cntc+1))-(1<<cnt)-1;
}
else{
ans=-1;
}
if(get_len(ans)>len){
ans=-1;
}
write_endl(ans);
return 0;
}

CQOI2013vp记的更多相关文章

  1. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  2. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

  3. 这些年一直记不住的 Java I/O

    参考资料 该文中的内容来源于 Oracle 的官方文档.Oracle 在 Java 方面的文档是非常完善的.对 Java 8 感兴趣的朋友,可以从这个总入口 Java SE 8 Documentati ...

  4. 千回百折:百度Java研发offer斩获记和经验分享

    起因 面试过程 等待offer的过程中悟道 Java面试常考知识点个人总结 过程 百度——作为国内互联网的巨头之一,最近的一些风波对其褒贬不一,但是类似事件不是第一次发生,也绝对不是最后一次,对于真的 ...

  5. 记一次nginx部署yii2项目时502 bad gateway错误的排查

    周六闲来无事,就试着安装和部署下yii2,安装过程没什么问题,但部署到nginx上时遇到了502 bad gatewary问题,折腾了半天才搞定.这个问题是我以前在部署yii2时没有遇到过的,因此记在 ...

  6. 原生JS实战:写了个一边玩游戏,一边记JS的API的游戏

    本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5878913.html 本程序[一边玩游戏,一边记JS的API]是本人的个 ...

  7. ArcGIS中的标注和注记

    在ArcMap中可以使用标注和注记来识别要素,选择标注或注记取决于你需要如何控制文本显示以及在ArcMap中如何存储文本. 1.标注只是临时显示相关数据或字段 2.标注用于长时间保存数据以及显示方式. ...

  8. 记处理线上记录垃圾日志 The view 'Error' or its master was not found

    最近监控线上日志,网站是ASP.NET MVC 开发的,发现不少错误日志都记录同样的内容: The view 'Error' or its master was not found or no vie ...

  9. 算法是什么我记不住,But i do it my way. 解一道滴滴出行秋招编程题。

    只因在今日头条刷到一篇文章,我就这样伤害我自己,手贱. 刷头条看到一篇文章写的滴滴出行2017秋招编程题,后来发现原文在这里http://www.cnblogs.com/SHERO-Vae/p/588 ...

  10. thusc2016游记&&滚粗记&&酱油记

    #include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs.com/w ...

随机推荐

  1. Eclipse's Import error and remove

    1.导入项目之前,请确认工作空间编码已设置为utf-8:window->Preferences->General->Wrokspace->Text file encoding- ...

  2. vue打包记录

    这里的确是css以及js文件的路径问题,但解决时并不需要手动改路径或者加一段判断去修改,最方便的办法时在项目打包前的vue.config.js里面将publicPath属性添加或者修改为 public ...

  3. Codeforces Round #809 (Div. 2) A-E

    Codeforces Round #809 (Div. 2) 2022/7/19 下午VP 传送门:https://codeforces.com/contest/1706 A. Another Str ...

  4. 转发:前端组件化之Monorepo方案实战

    前言 在上一篇的前端组件化方案探究中,我们研究了什么是组件化以及我们为什么需要组件化.也调研和测试了一些开源项目,并且在使用.学习.研究.对比之后最终确定了以 pnpm + workspace + c ...

  5. k8s探针

    探针是由kubelet对容器执行的定期诊断.要执行诊断,kubelet调用由容器实现的Handler.有三类处理程序: ExecAction:在容器内执行指定命令.如果命令退出时返回码为0认为诊断成功 ...

  6. 联邦学习开源框架FATE架构

    作者:京东科技 葛星宇 1.前言 本文除特殊说明外,所指的都是fate 1.9版本. fate资料存在着多处版本功能与发布的文档不匹配的情况,各个模块都有独立的文档,功能又有关联,坑比较多,首先要理清 ...

  7. mybatis-spring注解MapperScan的原理

    很多开发者应该都知道,我们只使用@MapperScan这个注解就可以把我们写的Mybatis的Mapper接口加载到Spring的容器中,不需要对每个Mapper接口加@Mapper这个注解了,加快了 ...

  8. flex弹性盒子中flex-grow与flex的区别

    ​大家在使用flex布局的时候很多情况下都会用到flex-grow这个属性, flex-grow 属性用于设置父元素剩余空间的瓜分比例, flex 属性是 flex-grow.flex-shrink  ...

  9. python基础篇:Python基础知识,帮助初学者快速入门

    Python是一种高级编程语言,它易于学习和使用,因此成为了许多人的首选编程语言.本文将介绍Python的基础知识,以帮助初学者快速入门. 安装Python 在开始学习Python之前,您需要安装Py ...

  10. 浅谈Array --JavaScript内置对象

    Array --JavaScript内置对象 描述 可以用一个变量存储多种数据类型的Array对象,Array不是关联数组,不能使用字符串作为索引访问数组元素,需要使用非负整数的下标访问数组中的元素. ...