由于题目是让我们统计个数,当我们确定了$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. WebXml文件与SpringMVC的联系

    WebXml文件与SpringMVC的联系 无论采用何种框架来进行Java Web的开发,只要是Web项目必须在WEB-INF下有web.xml,这是java规范. 当然,我们最早接触到Java We ...

  2. sarama的消费者组分析、使用

    以前老的sarama版本不支持消费者组的消费方式,所以大多数人都用sarama-cluster. 后来sarama支持了消费者组的消费方式,sarama-cluster也停止维护了,但网上关于sara ...

  3. go 连接MSSQLServer数据库【遇到的坑】

    前言:项目测试需要用到mssqlserver数据库连接,遇到坑,自己爬直接上代码:       package main import ( "database/sql" " ...

  4. System.Drawing Linux Centos7 The type initializer for 'Gdip' threw an exception

    System.Drawing 在linux使用时提示异常 The type initializer for 'Gdip' threw an exception 解决方案: yum install au ...

  5. $\text {FWT}$学习笔记

    \(\text {FWT}\) 学习笔记 正常项的\(\text {FWT}\) 在\(\text {OI}\)中,我们经常会碰到这种问题: 给出一个长度为\(n\)的序列\(a_{1,2,...,n ...

  6. 2020.5.4-ICPC Pacific Northwest Regional Contest 2019

    A. Radio Prize All boring tree-shaped lands are alike, while all exciting tree-shaped lands are exci ...

  7. 深度学习——手动实现残差网络ResNet 辛普森一家人物识别

    深度学习--手动实现残差网络 辛普森一家人物识别 目标 通过深度学习,训练模型识别辛普森一家人动画中的14个角色 最终实现92%-94%的识别准确率. 数据 ResNet介绍 论文地址 https:/ ...

  8. 3 Implementation: The Big Picture 实现:蓝图

    三.Implementation: The Big Picture 实现:蓝图 3.1 Layering of a .NET Solution .Net解决方案的分层 The picture belo ...

  9. Golang通脉之面向对象

    面向对象的三大特征: 封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式 继承:使得子类具有父类的属性和方法或者重新定义.追加属性和方法等 多态:不同对象中同种行为的不同实现方式 Go并不是一个纯 ...

  10. python web1

    ***本篇中的测试均需要使用python3完成. 攻击以下面脚本运作的服务器. 针对脚本的代码逻辑,写出生成利用任意代码执行漏洞的恶意序列的脚本: 打开攻击机端口, 将生成的东西输入网页cookie: ...