分治

分治,分而治之;整天整夜的挂在嘴边....

其实就是将原问题分成n个规模较小而结构与原问题相似的子问题

然后递归地解决这些子问题,最后合并其结果就得到原问题大的解。

当n=2时的分治法又称二分法

分治——Divide and Conquer

因此Divide 和Conquer 是很重要的

分治一般分三个步骤:

1.分解(Divide):将原问题分成一系列子问题。

2.解决(Conquer):递归的解决个子问题。若子问题足够小,则可以直接求出

3.合并(combine):将子问题的结果合并成原问题的解

LIKE THIS:

分治的策略和解题思路:

 if 问题不可分{

      直接求出;

     返回问题的解;

else{

   对原问题进行分治;

   递归对每一个分治部分求解;

   归并整个问题,得出权问题的解;

在分治中较为重要的有快速幂

它是通过二进制与十进制的关系实现的,迭代式子:

(19)10=(10011)2

19=1*2^4+0*2^3+0*2^2+1*2^1+1*2^0

19=( ( ( (  (  (1)*2) +0) *2) +0) *2)+1)*2+1

B^19=B^16*B^2*B^1

B^19=((((((B)^2)^2)^2)*B^2)B

                  1    0    0   1    1

每次平方是必须的,但是只有对应2进制为1的时候,才乘B

我们的基本思路就变成把p转换为二进制,然后从二进制的最高位开始,如果当前二进制为1,那么乘B在平方,如果当前二进制位为0,只平方即可。结果就出来了。

*同余问题:*

(a+b+c) %k= ( (a+b)%k+c)%k

(a-b-c) %k=  (a-b)%k -c

(a*b*c) %k =a*b %k  *c  %k

   

除此之外还有归并排序:

参考代码:

int cnt=0;       // 逆序对个数
int a[100002], c[100002];
void worksort(int l,int  r) //r=右边界索引;  归并排序!
{
 int  mid,tmp,i,j;
 if(r>l+1)
 {
  mid=(l+r)/2;  //中间边界
  worksort(l,mid-1);
  worksort(mid,r);
  tmp=l;
  for(i=l,j=mid;i<=mid-1 && j<=r;)   //l r, mid 表示下标,并不是具体的值??
  {
   if(a[i]>a[j])
   {
    c[tmp++]=a[j++];
    cnt+=mid-i;    //排序找逆序对个数,
   }
   else
    c[tmp++]=a[i++];
  }
  if(j<=r)
   for(;j<=r;j++)  c[tmp++]=a[j];
  else
   for(;i<=mid-1;i++)  c[tmp++]=a[i];
  for(i=l;i<=r;i++) a[i]=c[i];
 }
 else
 {
  if (l+1==r)
   if (a[l]>a[r])
   {
    swap(a[l],a[r]);
    cnt++;
   }
 }
}

分治是一种解题的策略,它的基本思想是:“如果整个问题比较复杂,可以将问题分化,各个击破。”

分治包含“分”和“治”两层含义,如何分,分后如何“治”成为解决问题的关键所在

不是所有的问题都可以采用分治,只有那些能将问题分成与原 问题类似的子问题,并且归并后符合原问题质的
 问题,才能进行分治

分治可进行二分,三分等等,具体怎么分,需看问题的性质和分治后的效果。

只有深刻地领会分治的思想,认真分析分治后可能产生的预期效率,才能灵活地运用分治思想解决实际问题。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值