首页 > 其他分享 >折半搜索学习笔记

折半搜索学习笔记

时间:2024-10-22 14:32:22浏览次数:1  
标签:折半 end dep text 笔记 return 搜索 tot quad

引入

\(1.\text{以经典例题引入:}\)

有一个长度为n的序列a,任选一些数求能组成的小于m的数的方案数(0不算)

\(\quad\text{看完题目第一反应,这不就是裸01背包吗?m为容量}\) \(a_i\text{为价值和体积,轻松AC。}\)

\(\quad\text{我们再来看一下数据范围}\ n\le40\ a_i\le10^9\ m\le4*10^{10}\)

\(\quad\text{额...这}\ m\ \text{大的离谱,总不能定义个 }f\left[40000000000 \right]\)。

\(\quad\text{于是折半搜索就这样出现了。}\)


介绍

\(1.\text{何为折半搜索?}\)

\(\quad\text{故名思义,就是把一个序列从中间分开,分别对两边搜索。}\)

$\quad\text{回到开篇例题,我们将序列}\ n\ \text{分为}1\sim \dfrac{n}{2} \ \text{和\ }\dfrac{n}{2}+1\sim n\ \text{两个序列。} $

\(\quad\text{然后分别搜索,决策为选和不选,将组成的数放入一个数组。}\)

\(\quad\text{这样我们得到两个数组}\ f[ \ ]\ s[\ ]\ \text{分别为两个序列所能组成的数。}\)

\(\quad\text{将}\ f[\ ]\ \text{排序后遍历}\ s[\ ]\ \text{每次循环找到}\ f[\ ]\ \text{中第一个大于}\ m-s_i\ \text{的数。}\)

\(\quad\text{可以使用}upperbound\text{来寻找,加到}\ ans\ \text{就行了。}\)

\(2.\text{时间复杂度}\)

\(\quad\text{因为每次只搜了一半的序列,所以为}\ O(2* 2^{ \frac{n}{2}}+\dfrac{n}{2}* \dfrac{n}{2}log\dfrac{n}{2}+\dfrac{n}{2}log\dfrac{n}{2})(\text{乱算的})\)

\(\quad\text{反正约等于}\ O( 2^{\frac{n}{2}})\)。

\(3.\text{代码}\)

#include<bits/stdc++.h>
using namespace std;
#define LL long long

LL n,m,a[50],ans=0;
vector<LL> fi, sc;

inline LL read(){
  LL s=0,w=1;char ch;
  ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-'){w=-1;}ch=getchar();}
  while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
  return s*w;
}

void print(LL x){
  char F[200];LL cnt=0;
  if(x<0) {x=-x;putchar('-');}
  if(x==0){putchar('0');putchar('\n');return ;}
  while(x){F[++cnt]=x%10;x/=10;}
  while(cnt){putchar(F[cnt--]+'0');}
  putchar('\n');
  return ;
}

void dfs1(int dep,int end,int tot){
  if(tot+a[dep]>m){
      return;
  }
  if(dep>end)
      return;
  fi.push_back(tot + a[dep]);
  dfs1(dep + 1, end, tot + a[dep]);
  dfs1(dep + 1, end, tot);
  return;
}
void dfs2(int dep,int end,int tot){
  if(tot+a[dep]>m){
      return;
  }
  if(dep>end)
      return;
  sc.push_back(tot + a[dep]);
  dfs2(dep + 1, end, tot + a[dep]);
  dfs2(dep + 1, end, tot);
  return;
}

int main(){
  n = read(), m = read();
  for (int i = 1;i<=n;i++){
      a[i] = read();
  }
  fi.push_back(0);
  sc.push_back(0);
  dfs1(1, (n >> 2), 0);
  dfs2((n >> 2) + 1, n, 0);
  sort(fi.begin(), fi.end());
  for (vector<LL>::iterator it = sc.begin(); it != sc.end();it++){
      vector<LL>::iterator e=upper_bound(fi.begin(),fi.end(),m-*it);
      ans += e - fi.begin();
  }
  print(ans-1);
  return 0;
}

\(\quad\text{}\)


习题

\(1.\)P4799 [CEOI2015 Day2]世界冰球锦标赛

\(\quad\text{跟经典例题一样}\)

\(2.\)P3067 [USACO12OPEN]Balanced Cow Subsets

$\ \ $ SP11469 SUBSET - Balanced Cow Subsets

\(\quad\text{每次搜索有三种情况 左边 右边 不选 难点在判重。}\)

\(\quad\text{设前半搜索总和左为}a\ \text{右为b ,后半搜索为左c 右d}\)

\(\quad a+c=b+d \ \Longrightarrow \ a-b=d-c\)

\(\quad\text{可以用位运算和map来判重。}\)

发布时间:2022-05-02 21:35

标签:折半,end,dep,text,笔记,return,搜索,tot,quad
From: https://www.cnblogs.com/xingke233/p/18492669

相关文章

  • btslab笔记
    本文只涉及漏洞的验证与解题思路不进行安装等基础教学1.vulnerability.injection.sqlinjectionurl:https://172.16.26.44/btslab/vulnerability/ForumPosts.php?id=1第一步:判断注入类型字符型还是数字型:GET/btslab/vulnerability/ForumPosts.php?id=1GET/btslab/vulnera......
  • 【开源免费】基于SpringBoot+Vue.JS读书笔记共享平台(JAVA毕业设计)
    本文项目编号T029,文末自助获取源码\color{red}{T029,文末自助获取源码}......
  • 学习笔记10.21
    使用AI提示语设计公式、AI优化、Markdown模版、提示语智能体R(角色)T(任务)F(要求)C(说明)公式举例eg:你现在是一位高校大学英语教师,(角色)设计大学英语《XXX》单元的教学计划,(任务)给出教学目标、教学大纲、单元活动安排,教学策略,布置学生作业。(要求)要求按照5E教学策略设计教学活......
  • 苹果笔记本和微软Surface哪个更适合商务使用
    在商务环境中,选择合适的笔记本电脑对于提高工作效率至关重要。本文对苹果笔记本和微软Surface进行比较分析,探讨哪种更适合商务使用。主要考虑因素包括:1.性能和可靠性;2.操作系统与软件兼容性;3.设计与便携性;4.电池续航力;5.价格与性价比;6.售后服务与支持。通过全面的比较分析,可以帮......
  • 汇编语言学习笔记(一)基础知识
    指令和数据指令和数据是应用上的概念,在内存或磁盘上,两者没有任何区别,都是二进制信息。如同围棋中的棋子,在棋盒里没有任何区别,在对弈的时候才有不同的意义存储单元计算机最小信息单位为Bit,也就是一个二进制位。8个bit组成一个Byte.通常称之为字节1B=8Bit,1KB=1024B,1M=1024......
  • 汇编语言学习笔记(二)寄存器
    简介上文所说的总线,相对于CPU自身而言,属于外部总线。这些外部总线将CPU与外部芯片串联起来。其内部也有类似结构(运算器/控制器/寄存器/内部总线),组成一个完整的CPU。运算器进行计算处理寄存器进行数据存储控制器控制内部芯片内部总线串联内部芯片不同CPU,寄存器的数量与......
  • 基于启发式蝙蝠算法、粒子群算法、花轮询算法和布谷鸟搜索算法的换热器PI控制器优化(Ma
    ......
  • cmake学习笔记
    最近在学cmake的用法,参考了cmake使用详细教程(日常使用这一篇就足够了)这篇文章,这篇文章讲的很仔细,下面记录自己的学习过程。1、系统以及开发工具一开始想通过虚拟机安装Ubuntu和vscode,后面想到了之前本机Windows安装过wsl,wsl的就是Ubuntu,在wsl+本地vscode的开发下,很快就把文章......
  • 将有序数组转换为二叉搜索树
    给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。示例1:输入:nums=[-10,-3,0,5,9]输出:[0,-3,9,-10,null,5]解释:[0,-10,5,null,-3,null,9]也将被视为正确答案:示例2:输入:nums=[1,3]输出:[3,1]解释:[1,null,3]和[3......
  • JAVA中的JDBC学习总结 我的学习笔记
    JDBC学习总结我的学习笔记一、JDBC简介一、JDBC快速入门一、JDBCAPI详解1.DriverManager2.Connection3.Statement4.ResultSet5.PreparedStatement一、数据库连接池1.数据库连接池简介2.数据库连接池实现3.Druid数据库连接池一、JDBC简介1.JDBC概念JDBC就......