由于题目是让我们统计个数,当我们确定了$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]数蘑菇的更多相关文章

  1. [Luogu 2656] 采蘑菇

    Description 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖和ZYR经过某条小径一次,可以采 ...

  2. 洛谷——P2656 采蘑菇

    P2656 采蘑菇 题目描述 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖和ZYR经过某条小径一次, ...

  3. 洛谷—— P2656 采蘑菇

    https://www.luogu.org/problem/show?pid=2656 题目描述 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连 ...

  4. 细数 Windows Phone 灭亡的七宗罪(过程很详细,评论很精彩,但主要还是因为太慢了,生态跟不上,太贪了,厂商不愿意推广)

    曾梦想仗剑走天涯,看一看世界的繁华 年少的心有些轻狂,如今你四海为家 曾让你心疼的姑娘,如今已悄然无踪影 犹记得上大学攒钱买了第一台智能手机Lumia 520时,下载的第一首歌曲<曾经的你> ...

  5. F 采蘑菇的克拉莉丝

    这是一道树链剖分的题目: 很容易想到,我们在树剖后,对于操作1,直接单点修改: 对于答案查询,我们直接的时候,我们假设查询的点是3,那么我们在查询的时候可分为两部分: 第一部分:查找出除3这颗子树以外 ...

  6. 利用requets库采集蘑菇租房网的租房信息

    前言:对于我们任何一个漂泊在外的打工者,租房似乎都是我们必经的一个经历,对于我们而言,选择性价比最高,最适合自己的房源至关重要,本文就将利用爬虫技术采集蘑菇租房网上指定的房源信息,后续可以利用这些信息 ...

  7. Linux上如何查看物理CPU个数,核数,线程数

    首先,看看什么是超线程概念 超线程技术就是利用特殊的硬件指令,把两个逻辑内核模拟成两个物理芯片,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的 ...

  8. 微信小程序中利用时间选择器和js无计算实现定时器(将字符串或秒数转换成倒计时)

    转载注明出处 改成了一个单独的js文件,并修改代码增加了通用性,点击这里查看 今天写小程序,有一个需求就是用户选择时间,然后我这边就要开始倒计时. 因为小程序的限制,所以直接选用时间选择器作为选择定时 ...

  9. 数塔问题(DP算法)自底向上计算最大值

    Input 输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数 ...

随机推荐

  1. 腾讯混合云存储 TStor 系列再添新成员,并行存储一体机正式发布

    最近国内某大型互联网公司依靠其数据优势成功上市,可见数据的重要性,而数据和存储密不可分,您真的知道自己需要更高性能存储吗? 在当今数据爆发式增长的时代,数据已经成为很多行业最重要的资源,没有之一. 数 ...

  2. BIBD&SBIBD的矩阵题

    证明不存在 \(01\) 方阵 \(A\) 使得: \(A^TA=\begin{pmatrix}7&2&\dots &2\\2&7&\dots&2\\ ...

  3. JavaCPP快速入门(官方demo增强版)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. ScatterLayout分散布局在kv中的引用

    from kivy.uix.scatterlayout import ScatterLayout from kivy.app import App class ScatterLayoutWidget( ...

  5. Spring Cloud Alibaba整合Sentinel

    Spring Cloud Alibaba 整合 Sentinel 一.需求 二.实现步骤 1.下载 sentinel dashboard 2.服务提供者和消费者引入sentinel依赖 3.配置控制台 ...

  6. 《基于SIR的路边违停行为传播模型研究》

    My Focus: 路边违停 行为的传播模型; 学习基于SIR XXX模型的可行性分析.建立和结论分析 Author: 左忠义,王英英,包蕴 Mind Map:

  7. hdu 3635 Dragon Balls(并查集)

    题意: N个城市,每个城市有一个龙珠. 两个操作: 1.T A B:A城市的所有龙珠转移到B城市. 2.Q A:输出第A颗龙珠所在的城市,这个城市里所有的龙珠个数,第A颗龙珠总共到目前为止被转移了多少 ...

  8. Docker 18.03 Centos7.6 安装 内网

    首先访问https://download.docker.com/linux/centos/7/x86_64/stable/Packages/获取对应版本的rpm包docker包docker-ce-18 ...

  9. 记一次 Java 导出大批量 Excel 优化

    常用的excel导出方案,详情见Spring Boot 入门(十二):报表导出,对比poi.jxl和esayExcel的效率,其中jxl.esayEscel 底层都是基于 poi,它们仅仅是对 poi ...

  10. void * 是什么?

    最近遇到void *的问题无法解决,发现再也无法逃避了(以前都是采取悄悄绕过原则),于是我决定直面它. 在哪遇到了? 线程创建函数pthread_create()的最后一个参数void *arg,嗯? ...