关于递归与分治

关于递归

众所众知,递归是思想而不是算法。

从古至今,尽管人脑很高级,但好像人脑天生不适合模拟递归。

它为什么难以被理解呢?我认为是它的这种自身调用自身的方式看似简单,

但是实际上会建立一棵庞大的搜索树。人脑由于容易出错,而递归又是建立在上一层基础上的,所以可能越错越深。

那它的性质可以解决什么问题呢?

我觉得,它可以解决一些有前提,可分为多个阶段,每个阶段的状态十分明了的问题(怎么有点像dp?当然,dp可以借助递归思想来分析)

补充

同时,还可以通过搜索树的形态来看出这一点。

搜索树上每个节点为一个状态,每一个状态有且只有一个前驱,但可以扩展到多个不同的状态。那么由根节点(初态)到叶子节点(终态)的路径就是一个可能的问题解决的方案,或解决方案的形成过程

也就是说,如果一个问题可以一步一步解决,并且每一步都很相似,就可以试着递归解决。

例题

经典问题:

要把N个相同苹果放进M个不同盘子,允许空盘,共有几种不同方案

dfs大家都知道。想要不漏很简单。

那不重呢?

首先,为什么可以用dfs?
因为我们可以一个盘子一个盘子地决定放几个苹果。

然后,分析各个可行方案,例如
2 6 9 和 2 9 6

可以发现,如果两个方案排序后一样,那他们就属于同一方案。

所以我们可以控制dfs进行升序查找:

void dfs(int d,int p,int lst){
	if(d&&p>n) return;
	if(d==0||p>n){
		cnt++;
		return;
	}
	for(int i=lst;i<=d;i++){
		dfs(d-i,p+1,i);
	}
}

关于分治

分治是一种将问题划分成若干子问题,再解决子问题的一种思想。

问题
分治等于二分吗?二分是分治思想的一个应用。
二分为什么要求答案空间具有单调性?因为二分省力的关键,就在于它可以通过题目的性质而抛弃必然不可能为答案的一半。
如果没有单调性,那么就有可能抛弃掉答案,从而出错

假如一个问题可以被分为较为简单或分为最优与非最优的子问题,那么就可以使用分治思想。可见,递归与分治都涉及了“分步解决,大问题化小”的思想,因此分治可以用递归实现。

例题

经典问题:

给你三个整数 a,b,p,求 abmodp 其中,a,b,p<231

这么大,O(n)解决肯定不行

我们尝试划分问题,众所周知a2b=ab2

那么我们就只要每次把底数*底数,不就可以省去中间的步骤了吗

这就相当于,每次把问题缩小到一半,只不过是反着求解的罢了。

#include<bits/stdc++.h>
using namespace std;
long long a,b,p;
inline long long fpow(long long d,long long z,long long m)
{
	long long res=1;
	while(z>0)
	{
		if(z%2!=0) res=res*d%m;//z&1 == z%2!=0   
		d=d*d%m;
		z=z/2;//z>>=1 == z=floor(z/2) == z/2
	}
	res%=m;
	return res;
}
int main()
{
	cin>>a>>b>>p;
	cout<<a<<"^"<<b<<" mod "<<p<<"="<<fpow(a,b,p);
}

Ex

这是一个pj-,但是极端恶心的题目:
幂次方

其中,对于每一个二进制分解出的数,我们对它再进行分解,最后通过判断来合成答案。(递归)

#include<bits/stdc++.h>
using namespace std;
int n;
string ans;
int find(int &n1)
{
	int cnt=0;
	while(true)
	{
		if(pow(2,cnt+1)>n1) break;
		cnt++;
	}
	n1-=pow(2,cnt);
	return cnt;
}
void work(int idx)
{
	if(idx==1)
	{
	ans+="2";
	return;	
	} 
	if(idx==0)
	{
	ans+="2(0)";
	return;
	}
	ans+="2(";
	while(idx)
	{
	
	work(find(idx));
	if(idx) ans+="+";
	}
	ans+=")";
}
void make()
{
	while(n)
	{
		int l=find(n);
		work(l);
	//	cout<<"Debug:"<<l<<endl;
		ans+="+";
	}
	ans.pop_back();
	cout<<ans;
	return;
}
int main()
{
	cin>>n;
	make();
	return 0;
}

EOF

感谢观看。QwQ

posted @   haozexu  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示