什么是分而治之?

分而治之” ( Divide and conquer)方法 (又称“分治术”) ,是有效算法 设计中普遍采用的一种技术。 所谓“分而治之” 就是把一个复杂的算法问题按一定的“分解”方法分为等价的规模较小的若干部分,然后逐个解决,分别找出各部分的解,把各部分的解组成整个问题的解,这种朴素的思想来源于人们生活与工作的经验,也完全适合于技术领域。 诸如软件的体系结构设计、模块化设计都是分而治之的具体表现。

分而治之能将问题逐步分解,但并非可用于解决问题的算法,而是一种解决问题的思路。

分而治之算法是递归的,使用分而治之(D&C)解决问题的过程包括两个步骤:

  1. 找出递归边界条件,这种条件必须尽可能简单
  2. 不断地将问题分解(或者说缩小规模),直到符合递归边界条件

看着是不是挺简单的,确实,算法这东西难就难在如何将其应用到实际生活中去,而且,算法是学不完的,算法在我看来主要就是一种解题思路,能够帮我们更好的解决生活中的问题,算法可以帮我们更快更好的解决我们遇到的问题,我们学习算法主要是要掌握其中的思想,递归算法有很多很多,但是归根结底就是“分而治之”的思想,当我们掌握了这个思想,我们在面对一系列从未接触过的实际问题的时候,才有机会去利用我们的知识去解决它。

不是所有的分治算法都一定要比蛮力求解算法更高效。但是,通常使用分治算法所用的时间往往比其他方法要少。实际上,分治法孕育了计算机科学中许多最重要和最有效的算法。虽然,许多这类算法的经典例子大部分都为顺序算法,但应该知道,分治法对于并行计算也是非常理想的,因为各个子问题都可以由各自的CPU同时计算。

 在分治算法最典型的应用中,问题规模为n的实例往往被划分为两个规模为n/2的实例。更一般的情况下,问题规模为n的实例被划分为b个规模为n/b的实例(其中a个实例需要求解,a>=1,b>=1,a,b为常量)。从理论上分析分治算法运行时间的过程中,往往使用递推公式进行数学分析(离散数学中的递推关系)。为了简化分析,我们假设n是b的幂,对于算法的运行时间T(n),我们有以下递推式:  T(n) = aT(n/b) + f(n) (f(n)是一个函数,表示将b个较小规模问题的解合并起来所消耗的时间),该递推公式被称为通用分治递推式。显然,T(n)的增长次数取决于常量a和b以及f(n)的增长。


分而治之算法的案例

Problem:KI的斐波那契

Description

KI十分喜欢美丽而优雅的斐波那契数列,最近他新认识了一种斐波那契字符串,定义如下

f (0) = b, f (1) = a,

f (2) = f (1) + f (0) = ab,

f (3) = f (2) + f (1) = aba,

f (4) = f (3) + f (2) = abaab,

KI想知道 f (n) 中的第 m 位是什么,你可以帮他解决这个问题吗?

Input

第一行有一个整数 T ,表示测试组数。

接下来的每个测试组包含两个数 n, m 。

数据范围: T≤ 1000, 0 ≤ n ≤ 90, 1 ≤ m ≤ 1e18

Output

对于每个测试组,输出’a’或者’b’

Sample Input

5

4 1

5 3

10 22

22 233

66 2333333333333

Sample Output

a

a

a

b

a

思路:我们考虑到第n个字符串由第n-1个字符串个第n-2个字符串相加得到,如果我们要找第m个字符,m<=fib[n-1]的话,我们就可以转成求第n-1个字符串的第m个字符,否则,就转换成求第n-2个字符串的第m-fib[a-1]个字符。

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll f[100];
void dfs(int n, ll m)
{
    if(n == 0) {puts("b"); return;}
    if(n == 1) {puts("a"); return;}
    if(m <= f[n-1]) dfs(n-1, m);
    else dfs(n-2,m-f[n-1]);
}
int main()
{
    int t, n; ll m;
    f[0] = 1; f[1] = 1;
    for(int i = 2; i < 100; i++)
        f[i] = f[i-1] + f[i-2];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%lld",&n,&m);
        dfs(n, m);
    }
 
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值