题解

设\(f[p][a][b]\)表示询问了\(p\)次,答案是\(a,b\)是否会被猜出来

然后判断如果\(p = 1\)

第一个问的\(Alice\),那么\([s,\sqrt{nm}]\)约数只有一个,\(f[p][a][b] = 1\)否则为\(0\)

如果第一个问的\(Bob\),那么\(a + b - 2 * S <= 1\)那么\(f[p][a][b] = 1\)否则为\(0\)

剩下的按照\(p\)这次操作询问谁,且然后从可能的数对里找\(f[p - 1][i][j]\)为\(0\)的有几个,如果只有1个就猜出来了

同时还要保证,在某个人猜出来之后,另一个猜出来的人询问第\(T + 1\)回合刚好能被猜出来的数对中,也只会问出一个,那么答案就是\(a,b\)了

用记搜,跑得还是挺快的

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 20005
#define eps 1e-8
#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int f[25][505][505],cnt[505 * 505],g[505][505];
vector<int> v[505 * 505];
int S,T,k;
char c[25];
bool dp(int p,int a,int b) {
if(p == 0) return 0;
if(f[p][a][b] != -1) return f[p][a][b];
if(p == 1) {
if(k == 1) { if(cnt[a * b] > 1) f[p][a][b] = 0;
else f[p][a][b] = 1;
}
else {
if(a + b - 2 * S <= 1) f[p][a][b] = 1;
else f[p][a][b] = 0;
}
return f[p][a][b];
}
if(dp(p - 1,a,b)) return f[p][a][b] = 1;
if(p % 2 == k) {
int c = 0;
for(auto h : v[a * b]) {
if(!dp(p - 1,h,a * b / h)) ++c;
}
if(c == 1) f[p][a][b] = 1;
else f[p][a][b] = 0;
}
else {
int c = 0;
for(int i = S ; i <= (a + b) / 2 ; ++i) {
if(!dp(p - 1,i,a + b - i)) ++c;
}
if(c == 1) f[p][a][b] = 1;
else f[p][a][b] = 0;
}
return f[p][a][b];
}
bool check(int a,int b) {
if(g[a][b] != -1) return g[a][b];
int c = 0;
if((T + 2) % 2 == k) {
for(auto h : v[a * b]) {
if(dp(T + 1,h,a * b / h) && !dp(T,h,a * b / h)) ++c;
}
}
else {
for(int i = S ; i <= (a + b) / 2 ; ++i) {
if(dp(T + 1,i,a + b - i) && !dp(T,i,a + b - i)) ++c;
}
}
if(c == 1) g[a][b] = 1;
else g[a][b] = 0;
return g[a][b];
}
pii Solve() {
memset(f,-1,sizeof(f));
memset(cnt,0,sizeof(cnt));
memset(g,-1,sizeof(g));
for(int i = S * S ; i <= 500 * 500 ; ++i) {
int t = sqrt(i);
v[i].clear();
for(int j = S ; j <= t ; ++j) {
if(i % j == 0) {
cnt[i]++;
v[i].pb(j);
}
}
}
for(int s = S + S ; s <= 1000 ; ++s) {
for(int i = S ; i <= 500 ; ++i) {
if(i > s) break;
for(int j = i ; j <= s - i ; ++j) {
if(i + j > s) break;
if(dp(T + 1,i,j) && !dp(T,i,j) && check(i,j)) {return mp(i,j);}
}
}
}
}
int main() {
for(int i = 1 ; i <= 25 ; ++i) {
stringstream ss;
string num;
ss << i;
ss >> num;
string str1 = "guess/guess" + num + ".in";
FILE *fin = fopen(str1.c_str(),"r");
fscanf(fin,"%d%s%d",&S,c + 1,&T); string str2 = "answer/guess" + num + ".out";
FILE *fout = fopen(str2.c_str(),"w");
if(c[1] == 'A') k = 1;
else k = 0;
pii ans = Solve();
fprintf(fout,"%d %d\n",ans.fi,ans.se);
printf("OK with %d task\n",i);
}
return 0;
}

【LOJ】#2511. 「BJOI2018」双人猜数游戏的更多相关文章

  1. LOJ #2135. 「ZJOI2015」幻想乡战略游戏

    #2135. 「ZJOI2015」幻想乡战略游戏 链接 分析: 动态点分治,求加权重心,带修改. 考虑如果知道了一个点s,如何求答案,那么首先可以点分治的思想,求每个联通块内所有点到分治中心距离和,然 ...

  2. [BJOI2018]双人猜数游戏

    题解: 彻彻底底的思维题???还是挺难的.. 首先连样例解释都没给..没看题解搞了很久 大概就是 一个人要根据另一个人的决策来猜数 可以去看洛谷那篇题解的解释 然后我们用$f[A/B][i][j][k ...

  3. LOJ #2135. 「ZJOI2015」幻想乡战略游戏(点分树)

    题意 给你一颗 \(n\) 个点的树,每个点的度数不超过 \(20\) ,有 \(q\) 次修改点权的操作. 需要动态维护带权重心,也就是找到一个点 \(v\) 使得 \(\displaystyle ...

  4. 洛谷P4459/loj#2511 [BJOI2018]双人猜数游戏(博弈论)

    题面 传送门(loj) 传送门(洛谷) 题解 所以博弈论的本质就是爆搜么-- 题解 //minamoto #include<bits/stdc++.h> #define R registe ...

  5. [luogu4459][BJOI2018]双人猜数游戏(DP)

    https://zhaotiensn.blog.luogu.org/solution-p4459 从上面的题解中可以找到样例解释,并了解两个人的思维方式. A和B能从“不知道”到“知道”的唯一情况,就 ...

  6. 【洛谷4459】[BJOI2018] 双人猜数游戏(动态规划)

    点此看题面 大致题意: 一直有两个数\(m,n\),已知\(s\le m\le n\),且\(Alice\)和\(Bob\)二个"最强大佬"各知道\(mn\)和\(m+n\).每轮 ...

  7. loj 2135 「ZJOI2015」幻想乡战略游戏 - 动态点分治

    题目传送门 传送门 题目大意 给定一棵树,初始点权都为0,要求支持: 修改点权 询问带权重心 询问带权重心就在点分树上跑一下就行了.(枚举跳哪个子树更优) 剩下都是基础点分治. 学了一下11-dime ...

  8. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

  9. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

随机推荐

  1. eclipse 安装报错

    14 11:17:13] ERROR: org.eclipse.equinox.p2.transport.ecf code=1002 Unable to read repository at http ...

  2. 【bzoj2844】 albus就是要第一个出场

    http://www.lydsy.com/JudgeOnline/problem.php?id=2844 (题目链接) 题意 给出${n}$个数,它们可以异或出${n^2}$个数,将这些数从小到大排列 ...

  3. Python Socket函数及说明

  4. 解题:POJ 2888 Magic Bracelet

    题面 这题虽然很老了但是挺好的 仍然套Burnside引理(因为有限制你并不能套Polya定理),思路和这个题一样,问题主要是如何求方案. 思路是把放珠子的方案看成一张图,然后就巧妙的变成了一个经典的 ...

  5. 输入一个十进制的数到dx_ax,然后十六进制转十进制输出

    ;HtoD data segment n dw ? data ends stack segment db dup(?) stack ends code segment assume cs:code,s ...

  6. 螺旋队列和hiho1525逃离迷宫3

    我是真调不出错误了! hiho1525逃离迷宫3 #include <stdio.h> #include <stdlib.h> #include <math.h> ...

  7. 虚拟机中liunx安装教程

    目标:在Linux服务器上部署Java开发的网站  工具 VirtualBox-4.3.8:下载后安装. linux系统镜像: Centos国内镜像文件下载地址: http://centos.ustc ...

  8. 位运算符和unity Layers

    按位运算符:与(&).非(~).或(|).异或(^).<<(左移).>>(右移).位运算符主要用来对二进制位进行操作. 逻辑运算符:&&.||.!.逻辑 ...

  9. 质数——6N±1法

    6N±1法求素数 任何一个自然数,总可以表示成为如下的形式之一: 6N,6N+1,6N+2,6N+3,6N+4,6N+5 (N=0,1,2,…) 显然,当N≥1时,6N,6N+2,6N+3,6N+4都 ...

  10. 机器学习:分类算法性能指标之ROC曲线

    在介绍ROC曲线之前,先说说混淆矩阵及两个公式,因为这是ROC曲线计算的基础. 1.混淆矩阵的例子(是否点击广告): 说明: TP:预测的结果跟实际结果一致,都点击了广告. FP:预测结果点击了,但是 ...