来自一个懒人的分治讲解(1)

分治的基础思想是:大问题变成小问题,解决小问题后将答案合并为大问题的答案
分治法可以通俗的解释为:把一片领土分解,分解为若干块小部分,然后一块块地占领征服,被分解的可以是不同的政治派别或是其他什么,然后让他们彼此异化。
分治法的精髓:
分–将问题分解为规模更小的子问题;
治–将这些规模更小的子问题逐个击破;
合–将已解决的子问题合并,最终得出“母”问题的解;

(1)数学方面的利用
举个非常通俗易懂的例子:
将一万个一相加的结果是什么?
如果用“1+1+1+1+1+1+1……”那就要运行一万次
这时候怎么优化呢?
大家可以发现:1+1这个过程被重复了一万次
那么:我们把1+1看成一个整体,将整体带入运算
嘿!这时候恭喜少侠,你的程序只要运行5000次了
我们又发现1+1又是“1+1+1+1”的一部分
同样的把1+1看成整体再运算,再将它带入;
重复如下过程,最终的结果就是10000*1;

接下来我们看一个典例__快速幂(洛谷p1226)
题意如下:
输入b,p,k的值,求b^p mod k的值。其中b,p,k*k为长整型数。
首先很容易发现mod k并不是什么问题( (a*b)%c=((a%c)*(b%c))%c),问题在于b^k;
这个过程会进行大量的运算
跟前面想的一样:将q分解,q为偶数,算出b^q/2 * b^q/2即可;q为奇数,算出b^q/2 * b^q/x *b即可
(原理:设底数为x,则x^(a+b)=x^a*x^b)
接下来是代码部分

#include<cstdio>
#include<cstdio>
#include<iostream>
using  namespace  std;
long long mod(long long  a,long long b,long long c) {
    long long ans=1;
    while(b) 
    {
        if(b%2==1)
            ans=ans*a%c;
        a=a*a%c;
        b/=2;
    }
    return ans;
}
int main () {
    long long b,p,k;
    cin>>b>>p>>k;
    cout<<b<<"^"<<p<<" mod "<<k<<"=";
    cout<<mod(b,p,k)%k;
}

分治法在这方面还有一个妙用—-它可以用来高效的解方程
我们来看接下来这道题目
一元三次方程求解(洛谷p1024)
题意如下:
ax3+bx2+cx+d=0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值>=1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。
提示:记方程f(x)=0,若存在2个数x1和x2,且x1

    for(int x=-100;x<=100;x++)
    if(f(x)*f(x+1.0)<=0)
    search(x,x+1.0);

search的内部函数怎么写呢?
首先我们知道精度是多少(0.01)
然后我们知道一个大概范围
所以我们只要将大范围划分为几个小范围,在小范围内找符合条件的区间,然后在小范围内部再划分——直到要求的精度以下(即精度右边减左边小于精度)
接下来让我们看下代码

void search(float l,float r)
{
    float mid=(l+r)/2;
    if(r-l<0.001)
    {
        printf("%.2f ",mid); 
        return;

    }
    else if(f(mid)==0)
    {
        printf("%.2f ",mid);

    }
    else if(f(r)==0)
    {
        printf("%.2f ",r);

    }
    if(f(l)*f(mid)<0) search(l,mid);
    if(f(mid)*f(r)<0) search(mid,r);
}

其实这时候大家可以发现,这道题跟二分非常像————其实,分治可以说是二分的一种基础思想。将区间不断缩小直到我们的利用范围之内,而关键就是找到一些重复性或类似的计算过程将他们简化,将n的时间复杂度缩短为logn级,来提高我们的效率

这是我第一次写讲义,知识点题目都讲得不透彻,只是自己的一些观点,希望大家多多包涵

待会,就让我们走进第二部分的学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值