二分法(又称二分查找算法)

二分查找算法讲解

枚举查找也就是顺序查找。

实现原理就是逐个比较 a[0:n-1] 中的元素,直到找出元素 x 或搜索遍整个数组后确定 x 不在其中,或者说符合要求的元素在不在数组中。

最坏的情况下需要比较 N 次,时间复杂度是 O(n) 线性阶。

二分查找也就是折半查找。折半查找是将 N 个元素分成大致相同的两部分。选取中间元素与查找的的元素比较,或者与查找条件相比较,找到或者说找到下一次查找的半区。每次都将范围缩小至1/2,所以时间复杂度是 O(log2n),但是二分查找的前提是有序的,一般是从小到排列。

在有序表中(low,high,low<=high),取中间记录即 [(high+low)/2] 作为比较对象。

若给定值与中间记录的关键码相等,则查找成功
若给定值小于中间记录的关键码,则在中间记录的左半区继续查找
若给定值大于中间记录的关键码,则在中间记录的右半区继续查找
不断重复上述过程,直到查找成功,或所查找的区域无记录,查找失败。
在这里插入图片描述

分巧克力

题目描述:

儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有 N 块巧克力,其中第 i 块是 Hi×Wi 的方格组成的长方形。为了公平起见,小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足:

  1. 形状是正方形,边长是整数;
  2. 大小相同;

例如一块 6x5 的巧克力可以切出 6 块 2x2 的巧克力或者 2 块 3x3 的巧克力。

当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?

输入描述:

第一行包含两个整数 N,K (1≤N,K≤1e5)。

以下 N 行每行包含两个整数 Hi Wi (1≤Hi,Wi≤1e5)。

输入保证每位小朋友至少能获得一块 1x1 的巧克力。

输出描述:

输出切出的正方形巧克力最大可能的边长。

输入样例

2 10
6 5
5 6

输出样例

2

题目分析:

简单思路,边长的最大规模为 100000;我们可以枚举出所有的情况。按从大到小的顺序进行切割,直到找到满足要求的巧克力边长。

在判断边长是否满足条件时:求一块长方形(h * w)最多被分成的正方形(len * len)巧克力个数为:

cnt = (h / len) * (w / len)

代码:

def check(d):
    global w,h
    res = 0
    for i in range(len(w)):
        res += (w[i]//d) * (h[i]//d)
    if res >= k:  
    	return True
    return False
n,k = map(int,input().split())
w = []
h = []
for i in range(n):
    a,b = map(int,input().split())
    w.append(a)
    h.append(b)
L ,R = 1, 100000
while L < R:
    mid = (L+R)//2
    if check(mid):  
    	L = mid +1
    else :          .
    	R = mid
print(L-1)//即输出中值

M 次方根

题目描述:

小A最近在学高等数学,他发现了一道题,求三次根号下27。现在已知,小 A 开始计算,1 的三次方得1,2 的三次方得 8,3 的三次方得 27,然后他很高兴的填上了 3。

接着他要求 5 次根号下 164。然后他开始 1 的三次方得 1,2 的三次方得 8,3 的三次方得27…

直到他算到了秃头,也没有找到答案。

这时一旁的小 B 看不下去了,说这题答案又不是个整数。小 A 震惊,原来如此。作为程序高手的小 A,打算设计一个程序用于求解 M 次跟下N的值。

但是由于要考虑精度范围,答案必须要保留 7 位小数,连三次根号下 27 都要掰手指的小 A 又怎么会设计呢。请你帮小 A 设计一个程序用于求解 M 次根号 N。

数据范围:

1<= N <= 1e5
1<= M <= 100
且 M<N

输入描述:

第一行输入整数 N 和 M,数据间用空格隔开。

输出描述:

输出一个整数,并保留 7 位小数。
输入样例:

27 3

输出样例:

3.000000

题目分析

根据前面的知识,我们要找到一个具有单调性的数列,去二分。这个题的关键是我们要去二分什么,这里可以二分的是 a^M 中的 a,所以我们要先想办法设计出用于处理实数二分的代码。

代码:

n = 0.0
m = 0
l = 0.0
r = 0.0
mid = 0.0

eps = 0.00000001


def pd(a, m):
  c = 1.0
  cnt = int(m)

  while cnt > 0:
      c = c * a
      cnt -= 1

  if c >= n:
      return True

  else:
      return False


if __name__ == '__main__':

  n, m = input().split()

  l = 0
  r=n=int(n)

  while l + eps < r:

      mid = (l + r) / 2

      if (pd(mid, m)):
          r = mid

      else:
          l = mid

print("%.7f" % l)

一元三次方程求解

在这里插入图片描述

代码:

n = input().split()
a,b,c,d = eval(n[0]),eval(n[1]),eval(n[2]),eval(n[3])
def y(x):    
    return a*x*x*x+b*x*x+c*x+d
for i in range(-100,100):
    left=i
    right=i+1
    y1=y(left)
    y2=y(right)
    if y1==0:
        print("{:.2f}".format(left),end=" ")
    if y1*y2<0 :
        while (right-left) >= 0.001:    #eps=0.001
            mid = (left+right)/2
            if y(mid)*y(right) <=0:
                left = mid
            else:
                right = mid
        print("{:.2f}".format(right),end=" ")
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥都鼓捣的小yao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值