双人猜数游戏 题解
ainivolAGEM · · 题解
题目大意
Alice 和 Bob 两个人在玩“最强大佬”猜数游戏,主持人会先想两个数
解题思路
这道题乍一看还挺玄学的,就两个人在那说着说着不知道然后突然就都知道了。
认真分析一下,既然知道
举个样例 1 例子:
-
第一次提问,Bob 拿到的信息为
N + M = 16 ,他可以知道N,M 为5 + 11 或6 + 10 或7 + 9 或8 + 8 ,但是此时 Bob 没有任何信息排除任意一个选项,所以 Bob 不知道。 -
第二次提问,Alice 拿到的信息为
N \times M = 60 ,他可以知道N,M 为5 \times 12 或6 \times 10 ,但是 Bob 的不知道对于 Alice 并没有什么帮助,不能排除选项,所以 Alice 也不知道。 -
第三次提问,鉴于 Bob 的信息乘积分别为
55 ,60 ,63 和64 ,而 Alice 却不知道,所以可以得出乘积分解情况肯定不止一种,但是除了60 以外,其余三个数在合法的乘积分解情况中都只有一种,所以 Bob 可以确定。 -
第四次提问,鉴于 Alice 可得的和为
17 或16 ,而且 Bob 可以确定了,那么可以直接排除17 。因为如果 Bob 得到的和为17 ,17 还有N = 8 , M = 9 的情况,Bob 应该不知道,但是 Bob 直接知道了,所以绝对不是17 。排除完之后,Alice 就也可以确定了。
所以大致思路就是,每日根据自己的信息解出所有可能的组合,通过对方的信息筛掉其他的组合,最后剩下一个情况时就可以确定了。
看看这道题的数据,看起来范围并不是很大。所以我们直接枚举
怎么判断呢?可以用递归!这个递归的目的就是求出指定的
如果只需要一次回答了,就返回当前所有情况集合中是否只有一个元素。否则就两个人轮流搜索递归调用,把不符合的情况删去,把答案保存在一个 vector 里,在函数结束后检查
最后就是每个点用程序跑一遍,直接提交即可。
注意事项
递归需要加上记忆化,否则会 TLE。
AC code
这里给出用来跑的代码。
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef pair<ll,ll> P;
const int N=504;
ll s,beg;
unordered_map<ll,vector<bool>>mp[N][N];
string name;
vector<bool> dfs(ll n,ll m,ll t){
if(mp[n][m].count(t)){
return mp[n][m][t];
}
vector<P> a;
vector<P> b;
ll x=n*m;
for(int i=s;i<=x;i++){
if(x%i==0){
ll j=x/i;
if(i>j){
break;
}
a.push_back(P(i,j));
}
}
x=n+m;
for(int i=s;i<=x;i++){
ll j=x-i;
if(j<i){
break;
}
b.push_back(P(i,j));
}
vector<bool> ans;
if(beg&1){
ans.push_back(a.size()==1);
}else{
ans.push_back(b.size()==1);
}
if(t==1){
return ans;
}
vector<P> tmp;
for(int i=2;i<=t;i++){
if((i&1)==(beg&1)){
for(P x:a){
if(dfs(x.first,x.second,i-1)==ans){
tmp.push_back(x);
}
}
swap(tmp,a);
tmp.clear();
ans.push_back(a.size()==1);
}else{
for(P x:b){
if(dfs(x.first,x.second,i-1)==ans){
tmp.push_back(x);
}
}
swap(tmp,b);
tmp.clear();
ans.push_back(b.size()==1);
}
}
return mp[n][m][t]=ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll t;
cin>>s>>name>>t;
if(name[0]=='A'){
beg=1;
}else{
beg=2;
}
for(int sum=s+s;true;sum++){
for(int n=s;n<=sum;n++){
ll m=sum-n;
if(m<n){
break;
}
vector<bool> ans=dfs(n,m,t+2);
for(int i=0;i<t;i++){
if(ans[i]){
goto X;
}
}
if(ans[t]&&ans[t+1]){
cout<<n<<' '<<m;
exit(0);
}
X:;
}
}
}
最后,祝各位能 AC 这道题!