[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个整数 ...
随机推荐
- 腾讯混合云存储 TStor 系列再添新成员,并行存储一体机正式发布
最近国内某大型互联网公司依靠其数据优势成功上市,可见数据的重要性,而数据和存储密不可分,您真的知道自己需要更高性能存储吗? 在当今数据爆发式增长的时代,数据已经成为很多行业最重要的资源,没有之一. 数 ...
- BIBD&SBIBD的矩阵题
证明不存在 \(01\) 方阵 \(A\) 使得: \(A^TA=\begin{pmatrix}7&2&\dots &2\\2&7&\dots&2\\ ...
- JavaCPP快速入门(官方demo增强版)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- ScatterLayout分散布局在kv中的引用
from kivy.uix.scatterlayout import ScatterLayout from kivy.app import App class ScatterLayoutWidget( ...
- Spring Cloud Alibaba整合Sentinel
Spring Cloud Alibaba 整合 Sentinel 一.需求 二.实现步骤 1.下载 sentinel dashboard 2.服务提供者和消费者引入sentinel依赖 3.配置控制台 ...
- 《基于SIR的路边违停行为传播模型研究》
My Focus: 路边违停 行为的传播模型; 学习基于SIR XXX模型的可行性分析.建立和结论分析 Author: 左忠义,王英英,包蕴 Mind Map:
- hdu 3635 Dragon Balls(并查集)
题意: N个城市,每个城市有一个龙珠. 两个操作: 1.T A B:A城市的所有龙珠转移到B城市. 2.Q A:输出第A颗龙珠所在的城市,这个城市里所有的龙珠个数,第A颗龙珠总共到目前为止被转移了多少 ...
- Docker 18.03 Centos7.6 安装 内网
首先访问https://download.docker.com/linux/centos/7/x86_64/stable/Packages/获取对应版本的rpm包docker包docker-ce-18 ...
- 记一次 Java 导出大批量 Excel 优化
常用的excel导出方案,详情见Spring Boot 入门(十二):报表导出,对比poi.jxl和esayExcel的效率,其中jxl.esayEscel 底层都是基于 poi,它们仅仅是对 poi ...
- void * 是什么?
最近遇到void *的问题无法解决,发现再也无法逃避了(以前都是采取悄悄绕过原则),于是我决定直面它. 在哪遇到了? 线程创建函数pthread_create()的最后一个参数void *arg,嗯? ...