[loj3368]数蘑菇
由于题目是让我们统计个数,当我们确定了$k$个$p_{i}$都为0或1后,再用至多$\lceil \frac{n-k}{k}\rceil$次询问和$2(n-k)$个"$n$"即可求出答案
具体构造就是将这$k$个数放在一排,并在中间插入未确定的$k$个数,中间$k-1$个数中不同于确定的$k$个数则会贡献2的答案,最后一个位置上的数根据答案奇偶性即可确定
(可以发现对于"$n$",$10^{5}$的限制是很宽松的,因此以下都不考虑对"$n$"的影响)
考虑如何找到这$k$个数:
有一个$2k-2$次的做法,每次询问$a=\{0,i\}$,最坏产生了$k-2$次$p_{i}=0$和$k-1$次$p_{i}=1$,那么再下一次及一定可行
当我们已经知道两个$p_{i}$相同的位置时(设为$x$和$y$)询问$,a=\{x,i,y,j\}$就可以求出$i$和$j$的类型(类似上面),最坏需要$2+(k-2)=k$次(恰好),算上$\lceil \frac{n-k}{k}\rceil$最小值大约为282,在$137\le k\le 146$时取到(由于自适应性,这些最坏情况都是会被取到的)
继续扩大范围,询问$a=\{x,i,y,j,z,k\}$,对答案分类讨论:
1.根据答案奇偶性,确定$k$,并令答案除以2;
2.若答案(除以2后)为0或2,则可以直接确定$i$和$j$;
3.否则(答案为1),我们无法得出$i$和$j$的状态,但可以利用$i$和$j$状态不同的条件
分类讨论,若已经确定的另一类型数量小于2,再加上一个未确定的数$l$,询问$a=\{x,l,y,i,z,j\}$,根据上述条件就可以直接确定$i,j,l$
否则,设另一类的两个分别为$x'$和$y'$,再加上两个未确定的数$l,t$,询问$a=\{x',i,y',x,j,y,l,z,t\}$,对答案分类讨论:
1.先将答案-1,因为$y'$与$x$一定会产生1的答案;
2.根据答案奇偶性,确定$t$,并令答案除以2;
3.当$i$改变后,$j$也对应改变,因此$i$对答案的影响为2(除以2后),而$l$对答案的影响为1,即通过答案(除以2后)的奇偶性可以确定$l$,再判断答案是否大于等于2可以确定$i$
这样最坏需要$3+2\lceil\frac{2k-5}{5}\rceil$,算上$\lceil \frac{n-k}{k}\rceil$最小值大约为254,在$k=154,159,160,164$时取到
细节优化:
1.在统计答案的过程中,我们可以确定最后一个位置上的数,不妨将其加入来增大$k$;
2.可以适当的调整$k$的值(我选的$k=100$只有96,选$k=110$就过了)
3.当$n<2k+3$,为了避免一些特判,可以直接做$o(n)$的暴力

1 #include "mushrooms.h"
2 #include<bits/stdc++.h>
3 using namespace std;
4 #define K 110
5 queue<int>q;
6 vector<int>a,v[2];
7 int get(){
8 int k=q.front();
9 q.pop();
10 return k;
11 }
12 void calc1(){
13 a.clear();
14 a.push_back(0);
15 a.push_back(get());
16 v[use_machine(a)].push_back(a[1]);
17 }
18 void calc2(){
19 int p=(v[0].size()<2);
20 a.clear();
21 a.push_back(v[p][0]);
22 a.push_back(get());
23 a.push_back(v[p][1]);
24 a.push_back(get());
25 int s=use_machine(a);
26 v[(s/2)^p].push_back(a[1]);
27 v[(s%2)^p].push_back(a[3]);
28 }
29 void calc3(){
30 int p=(v[0].size()<3);
31 a.clear();
32 a.push_back(v[p][0]);
33 a.push_back(get());
34 a.push_back(v[p][1]);
35 a.push_back(get());
36 a.push_back(v[p][2]);
37 a.push_back(get());
38 int s=use_machine(a);
39 v[(s%2)^p].push_back(a[5]);
40 s/=2;
41 if ((s==0)||(s==2)){
42 v[(s/2)^p].push_back(a[1]);
43 v[(s/2)^p].push_back(a[3]);
44 }
45 else{
46 if (v[p^1].size()<2){
47 a[5]=a[3];
48 a[3]=a[1];
49 a[1]=get();
50 int s=use_machine(a);
51 v[(s&1)^p].push_back(a[5]);
52 v[(s&1)^p^1].push_back(a[3]);
53 if ((s&1)==0)s-=2;
54 v[(s/2)^p].push_back(a[1]);
55 }
56 else{
57 a[0]=v[p^1][0];
58 a[2]=v[p^1][1];
59 a[4]=a[3];
60 a[3]=v[p][0];
61 a[5]=v[p][1];
62 a.push_back(get());
63 a.push_back(v[p][2]);
64 a.push_back(get());
65 int s=use_machine(a)-1;
66 v[(s&1)^p].push_back(a[8]);
67 s/=2;
68 v[(s&1)^p].push_back(a[6]);
69 v[(s/2)^p].push_back(a[4]);
70 v[(s/2)^p^1].push_back(a[1]);
71 }
72 }
73 }
74 int calc4(){
75 int p=(v[0].size()<v[1].size());
76 a.clear();
77 for(int i=0;(i<v[p].size())&&(!q.empty());i++){
78 a.push_back(v[p][i]);
79 a.push_back(get());
80 }
81 int s=use_machine(a);
82 v[(s&1)^p].push_back(a[a.size()-1]);
83 if (p)return s/2;
84 return a.size()/2-s/2-1;
85 }
86 int count_mushrooms(int n){
87 v[0].push_back(0);
88 for(int i=1;i<n;i++)q.push(i);
89 if (n<2*K+3){
90 while (!q.empty())calc1();
91 return v[0].size();
92 }
93 while (max(v[0].size(),v[1].size())<2)calc1();
94 while (max(v[0].size(),v[1].size())<3)calc2();
95 while (max(v[0].size(),v[1].size())<K)calc3();
96 int ans=0;
97 while (!q.empty())ans+=calc4();
98 return ans+v[0].size();
99 }
[loj3368]数蘑菇的更多相关文章
- [Luogu 2656] 采蘑菇
Description 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖和ZYR经过某条小径一次,可以采 ...
- 洛谷——P2656 采蘑菇
P2656 采蘑菇 题目描述 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖和ZYR经过某条小径一次, ...
- 洛谷—— P2656 采蘑菇
https://www.luogu.org/problem/show?pid=2656 题目描述 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连 ...
- 细数 Windows Phone 灭亡的七宗罪(过程很详细,评论很精彩,但主要还是因为太慢了,生态跟不上,太贪了,厂商不愿意推广)
曾梦想仗剑走天涯,看一看世界的繁华 年少的心有些轻狂,如今你四海为家 曾让你心疼的姑娘,如今已悄然无踪影 犹记得上大学攒钱买了第一台智能手机Lumia 520时,下载的第一首歌曲<曾经的你> ...
- F 采蘑菇的克拉莉丝
这是一道树链剖分的题目: 很容易想到,我们在树剖后,对于操作1,直接单点修改: 对于答案查询,我们直接的时候,我们假设查询的点是3,那么我们在查询的时候可分为两部分: 第一部分:查找出除3这颗子树以外 ...
- 利用requets库采集蘑菇租房网的租房信息
前言:对于我们任何一个漂泊在外的打工者,租房似乎都是我们必经的一个经历,对于我们而言,选择性价比最高,最适合自己的房源至关重要,本文就将利用爬虫技术采集蘑菇租房网上指定的房源信息,后续可以利用这些信息 ...
- Linux上如何查看物理CPU个数,核数,线程数
首先,看看什么是超线程概念 超线程技术就是利用特殊的硬件指令,把两个逻辑内核模拟成两个物理芯片,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的 ...
- 微信小程序中利用时间选择器和js无计算实现定时器(将字符串或秒数转换成倒计时)
转载注明出处 改成了一个单独的js文件,并修改代码增加了通用性,点击这里查看 今天写小程序,有一个需求就是用户选择时间,然后我这边就要开始倒计时. 因为小程序的限制,所以直接选用时间选择器作为选择定时 ...
- 数塔问题(DP算法)自底向上计算最大值
Input 输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数 ...
随机推荐
- Windows下node-gyp查找VS安装路径简单解析
node-gyp的作用我已经不想赘述了,这里给一个我之前文章的链接:cnblogs看这里,知乎看这里.本文主要从源码入手,介绍node-gyp查找VisualStudio的过程 为了方便我们研究nod ...
- 小白自制Linux开发板 番外篇 一 modprobe加载驱动问题(转载整理)
使用modprobe加载驱动 转载地址:https://blog.csdn.net/qq_39101111/article/details/78773362 前面我们提到,modprobe并不需要指定 ...
- Docker--harbor私有仓库部署与管理
目录 一.Harbor简介 二.Harbor 部署 三.维护管理Harbor 一.Harbor简介 1.什么是Harbor ? Harbor 是 VMware 公司开源的企业级 Docker Re ...
- javascript-jquery介绍
jquery优势 1.轻量级 2.强大的选择器 3.出色的DOM封装 4.可靠的事件处理机制 5.完善的Ajax 6.不污染顶级变量 7.出色的浏览器兼容 8.链式操作方式 9.隐式迭代 10.行为层 ...
- Scrum Meeting 0531
零.说明 日期:2021-5-31 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 困难 qsy PM&前端 完成后端管 ...
- BUAA_2020_软件工程_个人项目作业
作业抬头(1') 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 我在这个课程的目标是 了解软件工程的技术,掌握工程化开发的能力 这 ...
- 北航OO第四单元总结
OO最后一次博客作业--好聚好散 一.单元总结 作业一: 第一次是对类图进行解析,没有太大难度,只要根据讨论区提供的建议,新建两个类来存储相关数据即可实现. 作业二: 第二次作业的难度只有量的提升,然 ...
- Charles的简单用法
Charles的简单用法 一.抓电脑上 http 包 二.显示请求的 Request 和 Response 三.抓取电脑上 https 包 1.安装根证书 2.在钥匙串中启用根证书 3.配置哪些需要抓 ...
- 2021.8.6考试总结[NOIP模拟32]
T1 smooth 考场上水个了优先队列多带个$log$,前$80$分的点跑的飞快,后面直接萎了. 其实只需开$B$个队列,每次向对应队列中插入新的光滑数,就能保证队列中的数是单调的. 为了保证不重, ...
- BZOJ4919[Lydsy1706月赛]大根堆-------------线段树进阶
是不是每做道线段树进阶都要写个题解..根本不会写 Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切 ...