二分法

         二分法又称分半法,或对分法,是一种方程式根的近似值求法。二分法经常做为许多算法的优化途径,可以使一些O(n)的算法优化成O(logn)。所以在计算机竞赛中经常使用,为基础算法。

          二分法的思想:分而治之。将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同,(如果子问题的规模仍然不够小,则再划分为k个子问题),然后递归的求解这些子问题,最后用适当的方法将各个子问题的解合并成原问题的解。 

 1.二分查找

代码:

find_x(a, x)
    left = 0, right = a.length - 1
    while left <= right
        mid = (left + right) / 2
        if a[mid] == x
            return mid
        else if a[mid] < x
            left = mid + 1
        else
            right = mid - 1
    return NOT_FOUND

二分法进行数值计算:

      对于区间[a,b|上连续不间断且f(a)×f(b)<0的函数y=f(x),一定存在一个零点,也就是存在一个x使得f(x)=0。通过不断地把函数f(x)的零点所在的区间一分为二,使区间的两个端点逐步逼近零点,进而得到零点近似值的方法叫二分法。

 

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps = 1e-3;
double f(double x) {
    return pow(x, 4) + 5 * pow(x, 3) + 6 * pow(x, 2) + 7 * x + 4;
}
double cal(double y){
    if(f(0)>y||f(100)<y){
        return -1;
    }double l=0,r=100;
    while(r - l > eps){
        double mid=(l+r)/2;
        if(f(mid)>y){
            r=mid;
        }else{
            l=mid;
        }
    }
    return l;
}
int main () {
    double y;
    cin>>y;
    printf("%.3lf\n",cal(y));
    return 0;
}

两种二分快速幂:

package _二分法;

public class _快速幂_1 {

	static int mod = (int) 1e9;

	static long pow(int a, int b) {
		if (b == 0)
			return 1 % mod;
		long temp = pow(a, b / 2);
		if ((b & 1) != 0) {
			temp = temp * temp * a % mod;
		} else {
			temp = temp * temp % mod;
		}
		return temp;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		long ans=pow(4,6);
		System.out.println(ans);
	}

}
package _二分法;

public class _快速幂_2 {
//循环写法
// 计算4^6
	static int mod = (int) 1e9;

	static long pow(int a, int b) {
		int res = 1;
		while (b != 0) {
			if ((b & 1) != 0) {
				res = res * a % mod;
			}
			b >>= 1;
			a = a * a % mod;
		}
		return res;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		long t=pow(4,6);
		System.out.println(t);
	}

}

二分问题基本是二分的模板加上check函数检查答案。

01分数规划

           01分数规划是这样的一类问题,有一堆物品,每一个物品有一个收益ai,一个代价bi,我们要求一个方案,使选择的k个元素一:\frac{\sum a_{i}}{\sum b_{i}}最大值。
          首先我们来一道例题吧,01分数规划的大体方法都是一样的。给出n个物品,每个物品有两个属性a和b,选择k个元素,请问选择k个元素的:最大值是多少?

 

       我们先假设   f(x)=\frac{\sum_{0}^{n} x_{i}a_{i}}{\sum_{0}^{n} x_{i}b_{i}}, 其中xi只有两个取值0,1,表示是否选取第i个物品,并且\sum_{0}^{k}x_{i}=k  ,一共选k个元素。

继续假设有一组x在f(x)=v的时候,为最优解,上式变形如下: \sum_{0}^{n}x_{i}(a_{i}-vb_{i})=0,这时候对v二分求解就可以了。

代码如下:

package _二分法;

import java.util.Arrays;
import java.util.Scanner;

public class _01分数规划 {

	static int n;
	static double eps = 1e-5;
	static int[] a;
	static int[] b;
	static double[] temp;

	static double g(double v) {
		// 计算ax-v*bx
		for (int i = 0; i < n; i++) {
			temp[i] = a[i] - v * b[i];
		}
		Arrays.sort(temp);
		double sum = 0;
		for (int i = 0; i < n; i++) {
			sum += temp[i];
		}
		return sum;
	}

	static double cal() {
		double l = 0, r = 1e9;
		while (r - l > eps) {
			double mid = (l + r) / 2;
			if (g(mid) > 0) {
				l = mid;
			} else {
				r = mid;
			}
		}
		return l;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		a = new int[n];
		b = new int[n];
		temp = new double[n];
		for (int i = 0; i < n; i++)
			a[i] = sc.nextInt();
		for (int i = 0; i < n; i++)
			b[i] = sc.nextInt();
		System.out.println(cal());
	}

}

 

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值