首页 > 其他分享 >accoders NOI #5047. 猜数游戏 题解

accoders NOI #5047. 猜数游戏 题解

时间:2022-11-05 15:22:49浏览次数:40  
标签:第一轮 NOI 猜数 min 题解 Alice res Bob dp

题目描述

Alice 和 Bob 玩游戏。

Alice 有一个 \(1~n\) 中的正整数 \(y\)。Bob 不知道这个数。

游戏中的每一轮,Bob 选一个正整数 \(x\),并提问 Alice:\(y\) 是否大于等于 \(x\)?然后 Alice 需要回答是或否。

Alice 可以说至多一次谎。Bob 想要用尽量少的轮数确定 \(y\),Alice 希望 Bob 用的次数尽量多。

假设双方除第一轮外均采用最优策略。

作为一只 Goodeat,你既不是 Alice,也不是 Bob。

但你需要求出,对每个 \(x=1,2,...,n\),当 Bob 第一轮问 \(y\) 是否大于等于 \(x\) 且 Alice 第一轮回答了 是 的情况下,Bob 还需要多少轮能确定 \(y\)。

(Alice 第一轮有可能说谎。)

思路

算法一

由于加入了说谎的机制,我们不能像原来的猜数游戏一样二分求解。

我们可以把每次询问看成一次覆盖,把“否”的一端覆盖掉,那么当一个区间被覆盖了两次,这个区间便不可能成为答案。

暴力搜索期望得分 \(20\) 分。

算法二

容易发现,去掉覆盖两次的区间之后,最后一定是形如 \(x\) 个 \(0\),\(y\) 个 \(1\),再 \(z\) 个 \(0\)。

设 \(dp_{x,y,z}\) 表示出现上面的序列时,还需要猜多少次。转移可以枚举 Bob 第一轮的分界位置。

时间复杂度 \(O(n^4)\),期望得分 \(40\) 分。

算法三

考虑优化算法二。

我们注意到,在某个位置之前 Alice 回答大于更优,这个位置之后 Alice 回答小于更优。\(x,y\) 确定之后,对于不同 \(z\),这一位置一定是单调的,于是我们可以线性算出这个位置并记录。

时间复杂度变为 \(O(n^3)\),期望得分 \(70\) 分。

算法四

考虑 \(dp\) 的值域只有 \(O(\log n)\),且关于 \(z\) 单调,于是我们改写状态,定义 \(f_{x,y,w}\) 表示最大的 \(w\) 满足 \(dp_{x,y,z}\le k\)。

这样一来 \(f\) 的状态只有 \(O(n^2 \log n)\) 种,而且转移方法类似。

期望得分 \(100\) 分。

代码

// ubsan: undefined
// accoders
/*
 * Title: D. 猜数游戏
 * Source: accoders NOI-2022NOIP A层联测20
 * URL: http://47.92.197.167:5283/contest/275/problem/4
 * Author: Steven_lzx
 * Command: -std=c++23 -Wall -fno-ms-extensions
 * Date: 2022.11.4
 */
#include <bits/stdc++.h>
using namespace std;
const int MAXN=2001,MOD=998244353,INF=0x3f3f3f3f;
int n,dp[20][MAXN][MAXN],res,i,j,k;
int main()
{
    freopen("guess.in","r",stdin);
    freopen("guess.out","w",stdout);
    scanf("%d",&n);
    for(i=0;i<20;i++)
        for(j=0;j<=2000;j++)
            for(k=0;k<=2000;k++)
                dp[i][j][k]=-INF;
    dp[0][0][1]=dp[0][1][0]=0;
    dp[0][0][0]=1;
    for(res=1;res<20;res++)
    {
        for(k=0;k<=n;k++)//k:mid
        {
            for(i=0;i<=n-k;i++)
            {
                j=dp[res-1][k][i]+dp[res-1][0][k];
                if(j>=0)
                {
                    j=min(j,n-k);
                    dp[res][k][i]=max(dp[res][k][i],j);
                    dp[res][k][j]=max(dp[res][k][j],i);
                }
            }
            for(i=0;i<=k;i++)
            {
                j=k-i;
                if(dp[res-1][i][j]>=0&&dp[res-1][j][i]>=0)
                    dp[res][k][min(dp[res-1][i][j],n-k)]=max(dp[res][k][min(dp[res-1][i][j],n-k)],min(dp[res-1][j][i],n-k));
            }
            for(i=n-k+1;i>=0;i--)
                dp[res][k][i]=max(dp[res][k][i],dp[res][k][i+1]);
        }
    }
    for(i=1;i<=n;i++)
    {
        j=0;
        while(dp[j][n-i+1][i-1]<0)
            j++;
        printf("%d ",j);
    }
    putchar('\n');
    fclose(stdin);
    fclose(stdout);
    return 0;
}

标签:第一轮,NOI,猜数,min,题解,Alice,res,Bob,dp
From: https://www.cnblogs.com/2020gyk080/p/16860258.html

相关文章

  • 【杂题汇总】NOIP 2022 杂题目录
    这里单纯的是一些题目,看到有意思的题会在这里记下来,也可以当做Todolist啦解析的话在这里[ARC147E]Examination[CF573E]BearandBowling[CF498D]TrafficJamsi......
  • 「题解」Codeforces 1612F Armor and Weapons
    首先可以不管套件,假定\(n<m\),那么答案不超过\(\mathcal{O}(\logn+\frac{m}{n})\),也就是先倍增把\(n\)造出来,然后一步步造\(m\).答案这么小,那么常见的套路就是把答案......
  • 问题解决:vscode运行python找不到文件
    问题描述:使用VSCode执行Python代码调用其他文件时报FileNotFound错误,终于发现是VSCode工作路径默认是当前文件所在工作区的根目录,而不是当前文件所在目录。发生条件:根......
  • Google 正式开源 Paranoid
    Google近日正式开源了Paranoid,这是一个用于识别加密制品(cryptographicartifacts)中常见漏洞的项目。​​​​Paranoid支持测试多个加密制品,其中包括如数字签名、通用伪......
  • noi 1.4 11晶晶赴约会
    描述晶晶的朋友贝贝约晶晶下周一起去看展览,但晶晶每周的1、3、5有课必须上课,请帮晶晶判断她能否接受贝贝的邀请,如果能输出YES;如果不能则输出NO。输入输入有一行,贝贝邀请......
  • 「题解」牛客练习赛105 F 胖头鱼头胖
    先对每个位置\(i\)对集合幂级数\(x^0+x^1+\cdots+x+x^{a_i}\)FWT,那么询问就是将区间里面所有FWT后的集合幂级数作点积再IFWT后提取\(x^s\)的系数。首先可以通......
  • P2484 [SDOI2011]打地鼠 题解
    P2484[SDOI2011]打地鼠题解目录P2484[SDOI2011]打地鼠题解题目分析思路代码题目P2484[SDOI2011]打地鼠题解分析锤子每次只能将每个洞里打掉一只地鼠,所以对于每......
  • P7365 [CTSC2002]颁奖典礼 题解
    一道神奇的有关网格的DP(一些大佬称其为暴力DP)。这里将“I”字母分为的三个部分称为第一,二,三部分。做法:设fi,j,k,l(l∈[1,3])表示第i行,当前在第l部分,区间[j,k]的......
  • 2022NOIP A层联测20
    [优化排序?]T2:给出二分图,左部任意节点和右部任意节点有边连接,边有边权,求最少边权使得所有节点联通。(n<=5000)正解kruscal跑最小生成树,发现\(n^2logn\)的sort会T,然后因为......
  • P1083 [NOIP2012 提高组] 借教室
    #include<iostream>usingnamespacestd;constintN=1e6+1;intn,m;inta[N];structnode{inttag,sum;node(){tag=sum=0;}v......