[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个整数 ...
随机推荐
- linux性能优化基础——iommu相关配置
此篇文档介绍了IOMMU相关的信息: https://blog.chaosjohn.com/Check-VT-D-or-IOMMU-under-Linux.html iommu和vt-d都是io半虚拟 ...
- 天脉2(ACoreOS653)操作系统学习01
天脉2(ACoreOS653)操作系统学习01 由于我的毕业设计涉及相关嵌入式操作系统,故最近学了学天脉2操作系统. 一.ARINC653标准 1.ARINC653标准是什么? ARINC 653 : ...
- 【UE4 调试】C++ 几种编译方法和小技巧
编译方法 Visual Studio 2019 编译 默认编译 UnrealVS 快速编译 Editor 编译 一般 vs 编译完后,Editor会跟着热编译(有声音) 如果发现编译后代码没更新到Ed ...
- activiti会签 多实例例子
在实际的业务中,可能存在存在这么一种情况,当流程运行到某一个环节时,可能需要同时多个人的参与,才可以完成此环节.此时就可以用到activiti的多实例来解决此问题. 一.将一个节点设置成多实例的方法: ...
- Noip模拟66 2021.10.2
T1 接力比赛 思路就是直接做背包$dp$,然后看看容量相同的相加的最大值. 考虑如何在$dp$过程中进行优化 注意到转移方程的第二维枚举容量没有必要从容量总和开始枚举 那么我们便转移边统计前缀和,从 ...
- 设计模式(1-2)-动态代理(newProxyInstance)
上节设计模式(1-1)-代理模式,讲了代理模式的静态代理与动态代理的写法.本节,会从Proxy.newProxyInstance() 这个方法开始讲,上一节文末的那个class文件怎么一步步的来的. ...
- 因为一个小小的Integer问题导致阿里一面没过,遗憾!
面试题:new Integer(112)和Integer.valueOf(112)的区别 面试官考察点猜想 这道题,考察的是对Integer这个对象原理的理解,关于这道题的变体有很多,我们会一一进行分 ...
- cf 11B Jumping Jack(贪心,数学证明一下,,)
题意: 给一个数X. 起始点为坐标0.第1步跳1格,第2步跳2格,第3步跳3格,.....以此类推. 每次可以向左跳或向右跳. 问最少跳几步可以到坐标X. 思路: 假设X是正数. 最快逼近X的方法是不 ...
- 使用vsftpd 搭建ftp服务
ftp 基础服务器基础知识 ftp有三种登录方式.匿名登录(所有用户).本地用户.虚拟用户(guest). FTP工作模式 主动模式:服务端从20端口主动向客户端发起链接. 控制端口21:数据传输端口 ...
- 分布式技术-Zookeeper概述
概述 Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目 在大数据技术生态圈中,zookeeper(动物管理员),Hadoop(大象),Hive(蜜蜂),Pig(猪) ...