组合博弈学习笔记

组合博弈学习笔记


说在前边

  1. 下面的博弈题目基本就是sg函数,搜必败必胜态,找规律,推策略。。。没有对理论进行深入了解。

HDU1527

搜索时发现,必败态的数对貌似有规律,首先他们的大小两个数的差值是逐个增加的。然后,差分打表,发现差值为1或者2.实在找不到规律了,OEIS了一发,是个黄金分割,学到了。

//**黄金分割**
//**a(n) = floor(n*phi), where phi = (1+sqrt(5))/2
//**1,3,4,6,8,9,11,12,14,16,17,19,21,22,24,25,27,29,30,32,33,35,37
//**特点: 在i附近,貌似有规律地浮动
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
typedef long long ll;
using namespace std;
bool f[1101][1011],vis[1112][1101];
int dfs(int x,int y) {if(x==0&&y==0) return 0;if(vis[x][y]) return f[x][y];vis[x][y]=vis[y][x]=1;rep(i,1,x) if(!dfs(x-i,y)) return f[x][y]=f[y][x]=1;rep(i,1,y) if(!dfs(x,y-i)) return f[x][y]=f[y][x]=1;rep(i,1,min(x,y)) if(!dfs(x-i,y-i)) return f[x][y]=f[y][x]=1;return f[x][y]=f[y][x]=0;
}
vector<int> v;
int main() {
//**
//    rep(i,1,550) rep(j,1,i) {
//        if(!dfs(i,j))printf("(%d,%d) = %d\n",i,j,dfs(i,j)),v.pb(j);//**第i对数之间差i
//    }
//    cout << (sqrt(5)+1)/2.0 << endl;
//    rep(i,0,(int)v.size()-1) {
//        printf("%d, ",v[i]);
//    }puts("");
//**ll a,b;while(scanf("%lld%lld",&a,&b) != EOF) {if(a>b) swap(a,b);ll t = b-a;ll ta = floor((sqrt(5.0)+1.0)*t/2.0);if(ta == a) puts("0");else puts("1");}return 0;
}

HDU1760

直接搜索即可,hash去重直接用map,hash二进制压位。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
typedef unsigned long long ull;
const int N = 55;
const int mod = 1000007;
using namespace std;
int n,m;
map<ull,bool> s;
char mp[N][N];
bool ck(int x,int y) {if(x>=1&&x+1<=n&&y>=1&&y+1<=m) {if(mp[x][y]=='0'&&mp[x][y+1]=='0'&&mp[x+1][y]=='0'&&mp[x+1][y+1]=='0')return 1;return 0;}return 0;
}
bool ack() {rep(i,1,n-1)rep(j,1,m-1)if(ck(i,j))return 1;return 0;
}
void put(int x,int y) {mp[x][y] = mp[x+1][y] = mp[x][y+1] = mp[x+1][y+1] = '1';
}
void del(int x,int y) {mp[x][y] = mp[x+1][y] = mp[x][y+1] = mp[x+1][y+1] = '0';
}
ull HS() { //hash 好好写ull hs = 0;rep(i,1,n) rep(j,1,m)if(mp[i][j]=='0')hs |= (1LL<<((i-1LL)*m+j-1LL));return hs;
}
int dfs() {ull hs = HS();if(s.find(hs)!=s.end()) return s[hs];if(!ack()) return s[hs]=0;int ans = 0;rep(i,1,n-1)rep(j,1,m-1) if(ck(i,j)){put(i,j);if(!dfs()) ans |= 1;del(i,j);}return s[hs]=ans;
}
int main() {while(scanf("%d%d",&n,&m) != EOF) {rep(i,1,n) scanf(" %s",mp[i]+1);s.clear();if(dfs())puts("Yes");else puts("No");}return 0;
}

HDU1847

直接预处理sg函数即可

#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
typedef long long ll;
const int N = 1010;
using namespace std;
int n, sg[N];
bool vis[N];
void init() {sg[0] = 0;rep(s,1,1000) {memset(vis,0,sizeof(vis));rep(i,0,10)if((s>=(1<<i)))vis[sg[s - (1<<i)]] = 1;rep(i,0,1000) if(!vis[i]) {sg[s] = i;break;}}
}
int main() {init();while(scanf("%d",&n)!=EOF) {if(sg[n] == 0) puts("Cici");else puts("Kiki");}return 0;
}

HDU2516

记忆化搜索必败态,必胜态,发现满足斐波那契数列。之前的dp写法我自己都没看懂。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
typedef long long ll;
using namespace std;//***
int dfs(int n,int x) {if(n==0)return 0;rep(i,1,min(2*x,n)) if(!dfs(n-i,i)) return 1;return 0;
}
int cal(int n) {rep(i,1,n-1) if(!dfs(n-i,i)) return 1;return 0;
}
void _init(int n) {rep(i,2,n) if(!cal(i)) printf("%d ",i);puts("");
}
//***vector<ll> v;
void init() {ll f0 = 1, f1 = 1, f2 = 2;while(f2<(1LL<<32LL)) {v.pb(f2);f0 = f1; f1 = f2; f2 = f1 + f0;}
//    for(auto x: v)printf("%lld ",x);puts("");
}
int main() {//**//_init(50);//**init();ll n;while(scanf("%lld",&n),n) {if(*lower_bound(v.begin(),v.end(),n)==n)puts("Second win");else puts("First win");}return 0;
}

HDU3951

直接暴力求一根链情况下的sg函数,然后发现长度大于1必胜。环的情况就很容易了。还有一种思路是对称的取硬币可以证明后手必胜。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
typedef long long ll;
const int N = 1e3 + 7;
using namespace std;
int sg[N],vis[N];
void init(int K) {sg[0] = 0;rep(s,1,100) {memset(vis,0,sizeof(vis));rep(k,1,K) rep(i,1,s) {if(s-(i+k-1)>=0) {vis[sg[i-1]^sg[s-(i+k-1)]]=s;}}rep(i,0,100) if(vis[i]!=s){sg[s]=i;break;}}rep(s,1,100)printf("%d ",sg[s]);puts("");
}
int main() {//**//rep(i,1,10)init(i);//对于一根链//当k=1时,奇数必胜//当k大于1时,大于0就必胜//**int T,C=0;scanf("%d",&T);while(T--) {ll n; int K;scanf("%lld%d",&n,&K);printf("Case %d: ",++C);if(K==1) {if((n-1)%2==1)puts("second");else puts("first");}else {if(n<=K) puts("first");else puts("second");}}return 0;
}

HDU4559

将格子拆为 2×i 的格子与 1×1 的格子的组合,把他们分别处理sg值然后异或起来。对于 1×1 的格子,sg值就是1,对于2*i的格子,可以直接求sg值,具体写法见代码。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
typedef long long ll;
const int N = 4750;
using namespace std;
int T,C=0,n,m,sg[N],vis[N],num[N];
void init() {sg[0] = sg[1] = 0;rep(s,2,4747) {rep(i,1,s) {int l = i-1, r = s-i;vis[sg[l]^1^sg[r]]=s; // 1*1if(i+1<=s) {l=i-1; r=s-(i+1);vis[sg[l]^sg[r]]=s; // 2*2}}rep(i,0,4747) if(vis[i]!=s){sg[s] = i; break;}}
}
int solve() {int t0, t1, ans;t0=t1=ans=0;rep(i,1,n) {if(num[i] == 1) t1^=1;if(num[i] == 0) ++t0;else {ans^=sg[t0];t0 = 0;}}(ans^=sg[t0])^=t1;return ans;
}
int main() {init();scanf("%d",&T);while(T--) {scanf("%d%d",&n,&m);rep(i,0,n) num[i]=vis[i]=0;rep(i,1,m) {int x,y;scanf("%d%d",&x,&y);++num[y];}printf("Case %d: ",++C);if(solve()) puts("Alice");else puts("Bob");}return 0;
}

HDU4642

每次反转一个位置右下角一定会翻转一次,如果Alice将它反转为0,则Bob一定会将它反转为1,则最后一定是Alice赢。反之同理。所以直接判最后一位是0还是1即可

#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
typedef long long ll;
using namespace std;
int n,m;
int main() {int T;scanf("%d",&T);while(T--) {scanf("%d%d",&n,&m);int x;rep(i,1,n)rep(j,1,m) scanf("%d",&x);if(x==1) puts("Alice");else puts("Bob");}return 0;
}

HDU5963

与上一题思路基本一致,子节点的修改都会对根节点上的对应边进行反转,所以直接判那条边是否为1即可,多条边,直接判断奇偶。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define MP make_pair
#define PII pair<int,int>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
map<PII,int> M;
int n,m,d[44444];
int main() {int T;scanf("%d",&T);while(T--) {scanf("%d%d",&n,&m);rep(i,1,n) d[i]=0; M.clear();rep(i,1,n-1) {int x,y,z;scanf("%d%d%d",&x,&y,&z);d[x]+=z;d[y]+=z;if(x > y) swap(x,y);M[MP(x,y)] = z;}rep(i,1,m) {int opt,x,y,z;scanf("%d",&opt);if(opt) {scanf("%d%d%d",&x,&y,&z);if(x>y)swap(x,y);int t = M[MP(x,y)];d[x]+=z; d[y]+=z;d[x]-=t; d[y]-=t;M[MP(x,y)] = z;}else {int x;scanf("%d",&x);if(d[x]%2)puts("Girls win!");else puts("Boys win!");}}}return 0;
}

转载于:https://www.cnblogs.com/RRRR-wys/p/9404862.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/320668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

winserver的consul部署实践与.net core客户端使用(附demo源码)

前言随着微服务兴起&#xff0c;服务的管理显得极其重要。都知道微服务就是”拆“&#xff0c;把臃肿的单块应用&#xff0c;拆分成多个轻量级的服务&#xff0c;每个服务可以在短周期内重构、迭代、交付。随着微服务的数量增多&#xff0c;因量变引起了质量&#xff0c;带来新…

P5075-[JSOI2012]分零食【dp,生成函数,FFT】

正题 题目链接:https://www.luogu.com.cn/problem/P5075 题目大意 mmm个糖分给AAA个小朋友&#xff0c;得到xxx个糖的小朋友可以贡献F(x)Ox2SxUF(x)Ox^2SxUF(x)Ox2SxU的贡献值。要求没有得到糖的小朋友一定是后面一段连续的序列&#xff0c;求所有方案的贡献值乘积之和。 解题…

【模拟】【递归】解压字符串(jzoj 1519)

解压字符串 jzoj 1519 题目大意&#xff1a; 有一串压缩过的字符串&#xff0c;将有重复的压缩成了s(~~)的形式&#xff08;s是一位数&#xff0c;例子&#xff1a;123123123压缩成‘3&#xff08;123&#xff09;’&#xff09;&#xff0c;现在要你解压出来&#xff0c;然…

Educational Codeforces Round 48

Educational Codeforces Round 48 C.Vasya And The Mushrooms 思路很简单&#xff0c;走法有一个统一形式就是先上下走&#xff0c;然后到某个位置左右一个来回。然后就推一下&#xff0c;后边那段的递推式子&#xff0c;枚举改变走法的位置即可。看出做法之后发现要推个式子&a…

微软发布Azure Service Fabric Mesh公开预览版

Service Fabric现在在云端有了一个新亲戚——Azure Service Fabric Mesh&#xff0c;Azure的一个完全托管服务&#xff0c;开发人员现在可以基于此服务部署和运行容器化应用程序。在去年五月的Build 2018大会期间首次亮相后&#xff0c;现在开始进行公开预览。在Build 2018大会…

【DP】楼梯(jzoj 1520)

楼梯 jzoj 1520 题目大意&#xff1a; 有n个楼梯&#xff0c;跳跃高度初始值是1&#xff0c;当往后一层时&#xff0c;跳跃高度就2&#xff0c;当跳跃只能跳跃到当前能跳到楼梯&#xff0c;且跳跃之后&#xff0c;跳跃高度变回1&#xff0c;问跳到第n层最少花几步 样例输入…

P5502-[JSOI2015]最大公约数【分治】

正题 题目链接:https://www.luogu.com.cn/problem/P5502 题目大意 nnn个数&#xff0c;求一个L,RL,RL,R使得最大化(R−L1)∗gcd(aL,aL1,aL1...aR−1,aR)(R-L1)*gcd(a_L,a_{L1},a_{L1}...a_{R-1},a_R)(R−L1)∗gcd(aL​,aL1​,aL1​...aR−1​,aR​) 解题思路 考虑分治&#x…

牛客网暑期ACM多校训练营(第五场)

牛客网暑期ACM多校训练营&#xff08;第五场&#xff09; A. gpa 二分答案&#xff0c;然后就转化为是否满足\(\frac {\sum s[i]c[i]}{\sum s[i]} ≥ D\), \(\sum s[i]c[i] ≥ \sum s[i]D\), \(\sum s[i](c[i]-D) ≥ 0\) 显然科目越少gpa越高&#xff0c;于是去掉最小的k个判断…

.NET Core TDD前传: 编写易于测试的代码 -- 缝

有时候不是我们不想做单元测试, 而是这代码写的实在是没法测试....举个例子, 如果一辆汽车在产出后没完成测试, 那么没人敢去驾驶它. 代码也是一样的, 如果项目未能进行该做的测试, 那么客户就不敢去使用它, 即使使用了也会遇到“车祸”. 为什么要测试/测试的好处它可以尽早发现…

【数位DP】好数(jzoj 1521)

好数 jzoj 1521 题目大意&#xff1a; 定义好数为转换为二进制后&#xff0c;有至少三个连续的位相同的数&#xff0c;现在要求一个范围内的好数个数 样例输入 0 16样例输出 5数据范围限制 0 < Low < UP < 2147483647 提示 提示&#xff1a; 对于50%测试&…

P4294-[WC2008]游览计划【斯坦纳树】

正题 题目链接:https://www.luogu.com.cn/problem/P4294 题目大意 n∗mn*mn∗m的网格&#xff0c;每个格子的修建费用不同&#xff0c;要求修建费用最小连接所有关键点。 解题思路 设fs,i,jf_{s,i,j}fs,i,j​表示目前连接关键点状态为sss&#xff0c;在(i,j)(i,j)(i,j)这个位…

「LibreOJ NOIP Round #1」旅游路线

「LibreOJ NOIP Round #1」旅游路线 题目链接 做法&#xff1a; 首先肯定要预处理些东西&#xff0c;来使单词询问达到\(o(logn)\)或者\(o(1)\)的复杂度&#xff0c;又因为距离这个东西的范围太大&#xff0c;我们考虑预处理一些费用相关的东西。考虑\(dp[s][j]\)表示从s出发花…

【招聘(北京)】东方国信 工业互联网

从工业领域的业务出发&#xff0c;结合现有的物联网、大数据、云计算等技术进行体系化建设。自主研发的智能检测传感器、自主开发的部署在生产单位的专家系统、自主设计通讯交互协议、自主开发的工业物联网通讯框架、自主开发的分布式存储中间件、自主研发的机理模型&#xff0…

纪中C组模拟赛总结(2019.7.5)

成绩&#xff1a; rankrankrank是有算其他dalaodalaodalao的 rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3T4T4T4888lyflyflyf300300300100100100100100100100100100000111111hkyhkyhky280280280100100100100100100808080000121212wjjwjjwjj2702702701001001001…

2020牛客NOIP赛前集训营提高组(第四场)B-色球【链表】

正题 题目链接:https://ac.nowcoder.com/acm/contest/7611/B 题目大意 nnn个杯子&#xff0c;mmm个操作 在第zzz个杯子中依次加入xxx个颜色为yyy的球在第yyy个杯子中取出xxx个球&#xff0c;并询问最后一个拿出的球将第xxx个杯子的球依次拿出放入第yyy个杯子中 解题思路 每次…

POJ3613

POJ3613 题意&#xff1a;n条边构成的最短路 做法&#xff1a;倍增floyd #include <cstdio> #include <cstring> #include <algorithm> #define rep(i,a,b) for(int ia;i<b;i) typedef long long ll; const int N 207; const int inf 0x3f3f3f3f; using…

Ocelot-基于.NET Core的开源网关实现

写在前面API网关是系统内部服务暴露在外部的一个访问入口&#xff0c;类似于代理服务器&#xff0c;就像一个公司的门卫承担着寻址、限制进入、安全检查、位置引导等工作&#xff0c;我们可以形象的用下图来表示&#xff1a; 外部设备需要访问内部系统服务时必须要通过我们的AP…

【模拟】阿里郎(jzoj 2012)

阿里郎 jzoj 2012 题目大意&#xff1a; 有一个数n&#xff0c;求出它的所有约数d&#xff0c;有多少个约数就分多少种情况&#xff0c;每次分为d组&#xff0c;把1,d1,2d1……n-d1分为一组&#xff0c;以此类推&#xff0c;把2,d2,2d2……n-d2分为另一组&#xff0c;然后同…

[2020.10.25NOIP模拟赛]序列【Splay】

正题 题目链接:https://www.luogu.com.cn/problem/U136336?contestId36038 题目大意 第iii次找到第iii大的数字位置xix_ixi​并且翻转[i,xi][i,x_i][i,xi​]&#xff0c;求输出序列xxx 解题思路 记录一下每个排名在SplaySplaySplay中的位置&#xff0c;然后暴力翻转即可。 …

HDU2476

HDU2476 做法&#xff1a; 先想到用\(f[i]\)表示A的前i个字符变成B的最少涂得次数&#xff0c;不难写出方程&#xff0c;当\(A[i]≠B[i], f[i] max(f[j-1]cost[j][i])\), 当\(A[i]B[i]\)时&#xff0c;\(f[i]f[j-1]\) , \(cost[i][j]\) 表示将i到j涂成和B一样的最少的次数。现…