MiCode108 猜数字

本文探讨了一种基于数学家间猜数字游戏的算法问题,裁判选定正整数N及两个数字X,Y,通过告知玩家S和P数字的和与乘积,玩家需通过多次猜测确定数字。文章提供了具体的实现代码,包括使用set存储可能的数字组合,通过迭代减少可能性直至找到正确答案。

Description

相传,十八世纪的数学家喜欢玩一种猜数字的小游戏,规则如下: 首先裁判选定一个正整数数字 N (2 \leq N \leq 200)N(2≤N≤200),然后选择两个不同的整数X, Y (1 \leq X \le Y \leq N)X,Y(1≤X≤Y≤N) 裁判告诉玩家S这两个数字的和;告诉玩家P这两个数字的乘积 由玩家S开始,双方依次告诉裁判自己是否知道X, Y分别是多少,如果有一方知道,那么游戏就结束了!

例如,裁判先选定N = 10N=10并将NN的值告诉玩家,然后从1~N中选择X = 3, Y = 6X=3,Y=6,并将它们的总和9告诉给玩家S,将它们的乘积18告诉给玩家P:

玩家S:“我不知道这些数字”

玩家P:“我不知道这些数字”

玩家S:“我不知道这些数字”

玩家P:“我不知道这些数字”

玩家S:“哦,我知道这些数字了,他们是3和6”

数学家们都非常的聪明,他们总能用最少的次数推断出这些数字。

现在给定N和M (0 \leq M \leq 100)(0≤M≤100),M为玩家回答“我不知道这些数字”的次数,请你给出裁判选择的X,Y的组合有多少种?

Solution

这么长时间终于做出来了好开心.
哈哈, 请教的群里的大佬们, 看了他们的对话以及有dl友情提供了一个做法
鬼谷子问题
mPng

Code

#include <set>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include<ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
const int N = 50005;
set<pair<int, int> > sum[405], mul[N];

int main () {
    int n, m;
    while (scanf("%d,%d", &n, &m) == 2) {
        for (int i = 1; i <= n; i += 1)
            for (int j = i + 1; j <= n; j += 1) if (i != j)
                sum[i + j].insert(make_pair(i, j)),
                mul[i * j].insert(make_pair(i, j));
        int now_player = 1;
        for (int i = 0; i < m; i += 1, now_player ^= 1) {
            if (now_player & 1) {
                for (int j = 1; j <= n + n; j += 1)
                    if (sum[j].size() == 1) {
                        pair<int, int> Pair = *sum[j].begin();
                        sum[j].erase(sum[j].begin());
                        mul[Pair.first * Pair.second].erase(mul[Pair.first * Pair.second].find(Pair));
                    }
            } else {
                for (int j = 1; j <= n * n; j += 1)
                    if (mul[j].size() == 1) {
                        pair<int, int> Pair = *mul[j].begin();
                        mul[j].erase(mul[j].begin());
                        sum[Pair.first + Pair.second].erase(sum[Pair.first + Pair.second].find(Pair));
                    }
            }
        }
        int res = 0;
        if (now_player)
        for (int i = 1; i < n + n; i += 1)
            if (sum[i].size() == 1) res += 1;
        if (not now_player)
        for (int i = 1; i < n * n; i += 1)
            if (mul[i].size() == 1) res += 1;
        for (int i = 1; i < n + n; i += 1) sum[i].clear();
        for (int j = 1; j < n * n; j += 1) mul[j].clear();
        printf("%d\n", res);
    }
    return 0;
}

转载于:https://www.cnblogs.com/qdscwyy/p/9812600.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值