c++递推算法详解

合集下载

C++函数、递推、递归ppt课件

C++函数、递推、递归ppt课件

i = 7 s1 = 2 * (s2 + 1) ; s2 = s1 ;
// S(7) = 2 * (S(8) + 1) // s2 = s1 = S(7)
i = 6 s1 = 2 * (s2 + 1) ; s2 = s1 ;
// S(6) = 2 * (S(7) + 1) // s2 = s1 = S(6)
看一个简单的例子:
1 4
第九讲——函数、递推、递归
递归
有 5 个人坐在一起,问第 5 个人多少岁? 他说比第 4 个人 大两岁。问第 4 个人岁数,他说比第 3 个人大两岁。问第 3 个人,又说比第 2 个人大两岁。问第 2 个人,说比第 1 个人 大两岁。最后问第 1 个人,他说是 10 岁。请问第 5 个人多 大?
3
第九讲——函数、递推、递归
解题思路:
假设用 S(i) 表示第 i 天没吃之前的桃子数目;

S(1) 即为第 1 天所摘的桃子数; S(2) = S(1) * 1/2 – 1 第 2 天没吃之前的桃子数
S(3) = S(2) * 1/2 - 1 第 3 天没吃之前的桃子数


S(9) = S(8) * 1/2 - 1 第 9 天没吃之前的桃子数
= age(2) + 2 + 2 + 2 // c = age(2) + 2
= age(1) + 2 + 2 + 2 + 2;// c = 10;
2 2
计算年龄程序
第九讲——函数、递推、递归
2 3
第九讲——函数、递推、递归
递归算例(2)
用递归方法计算 n! 算法思路:

《c语言递归算法》课件

《c语言递归算法》课件
《C语言递归算法》PPT 课件
C语言递归算法是一种强大的编程技巧,通过函数自身调用实现问题的解决。 本课件将介绍递归算法的概念、实现方式、应用场景、优缺点以及与循环的 区别,同时还会通过案例演示帮助理解。
什么是递归算法?
基本概念
递归是指函数直接或间接地调用自身的过程。
递归特点
递归算法需要有基准条件和递推关系,用于结 束递归和推进递归过程。
递归算法的实现方式
递归函数
通过函数自身调用实现递归,需要定义递归函数和 递归终止条件。
递归流程图
通过流程图展示递归算法的执行过程,帮助理解递 归逻辑。
递归算法的应用场景
1 数学计算
递归算法可以用于解决数学问题,如斐波那契数列、阶乘等。
2 数据结构
递归算法在树、图等数据结构的遍历和搜索中有广泛应用。
递归算法的优点和缺点
优点
• 简化问题复杂度 • 代码结构清晰
缺点
• 执行效率较低 • 内存占用较高
递归算法与循环的区别
1
循环
2
迭代操作
3
递归
函数自身调用
区别
递归更直观,但消耗资源较多;循环更 高效,但代码可读性差。
递归算法的注意事项
1 递归终止条件
保证递归过程能够结束,否则可能导致死循 环。
2 堆栈溢出
过深的递归调用可能导致堆栈溢出,需要注 意递归深度。
递归算法的案例演示
斐波那契数列
通过递归实现斐波那契数列的计算。
二叉树遍历
通过递归遍历二叉树的各种方式。

递推算法(C 版)2017

递推算法(C  版)2017

【参考程序】
#include<iostream>
using namespace std;
int main()
{
int n,i,j,a[101][101];
cin>>n;
for (i=1;i<=n;i++)
for (j=1;j<=i;j++) cin>>a[i][j];
//输入数字三角形的值
for (i=n-1;i>=1;i--)
递推法是一种重要的数学方法,在数学的各个领域中都 有广泛的运用,也是计算机用于数值计算的一个重要算法。 这种算法特点是:一个问题的求解需一系列的计算,在已知 条件和所求问题之间总存在着某种相互联系的关系,在计算 时,如果可以找到前后过程之间的数量关系(即递推式), 那么,从问题出发逐步推到已知条件,此种方法叫逆推。无 论顺推还是逆推,其关键是要找到递推式。这种处理问题的 方法能使复杂运算化为若干步重复的简单运算,充分发挥出 计算机擅长于重复处理的特点。
【算法分析】 (1)面对上述问题,如果思考方法不恰当,要想获得问题的解答是相当
困难的。可以用递推方法归纳出问题解的一般规律。 (2)当n=1时,只能是一种铺法,铺法总数有示为x1=1。 (3)当n=2时:骨牌可以两个并列竖排,也可以并列横排,再无其他方法,
如下左图所示,因此,铺法总数表示为x2=2;
如上例:输入:2 3
输出:8 10
【算法分析】
1.计算正方形的个数s1
边长为1的正方形个数为n*m
边长为2的正方形个数为(n-1)*(m-1)
边长为3的正方形个数为(n-2)*(m-2)
…………
边长为min{n,m}的正方形个数为(m-min{n,m}+1)*(n-min{n,m}+1)

递推算法(C++版)

递推算法(C++版)

int main()
{
int n,i,j,a[101];
cout<<"input n:";
//输入骨牌数
cin>>n;
a[1]=1;a[2]=2;
cout<<"x[1]="<<a[1]<<endl;
cout<<"x[2]="<<a[2]<<endl;
for (i=3;i<=n;i++)
//递推过程
{
int n,m; cin>>m>>n; int m1=m,n1=n,s1=m*n; while (m1!=0&&n1!=0) {
m1--;n1--; s1+=m1*n1; } int s2=((m+1)*(n+1)*m*n)/4-s1; cout<<s1<<" "<<s2<<endl; }
//计算正方形的个数s1 // 计算长方形的个数s2
其实,本题稍加分析就能发现,要到达棋盘上的一个点,只能从左边过 来(我们称之为左点)或是从上面过来(我们称之为上点),所以根据加 法原理,到达某一点的路径数目,就等于到达其相邻的上点和左点的路径 数目之和,因此我们可以使用逐列(或逐行)递推的方法来求出从起点到 终点的路径数目。障碍点(马的控制点)也完全适用,只要将到达该点的 路径数目设置为0即可。
个正方形、多少个长方形(不包括正方形)。
例如:当 N=2, M=3时:
正方形的个数有8个:即边长为1的正方形有6个;边长为2的正方形有2个。

04.递推算法(C++版包括习题参考答案)

04.递推算法(C++版包括习题参考答案)
min{m , n}1 i 0
s 1=
(n i ) * (m i )
2.长方形和正方形的个数之和s 宽为1的长方形和正方形有m个,宽为2的长方形和正方形有 m-1个,┉┉,宽为m的长方形和正方形有1个; 长为1的长方形和正方形有n个,长为2的长方形和正方形有n1个,┉┉,长为n的长方形和正方形有1个; 根据乘法原理
【参考程序】 #include<iostream> using namespace std; int main() { int f[1001][2],n,i,x; cin>>n; f[1][1]=1;f[1][0]=9; for(i=2;i<=n;i++) { x=f[1][0]; if(i==n)x--; f[i][0]=(f[i-1][0]*x+f[i-1][1])%12345; f[i][1]=(f[i-1][1]*x+f[i-1][0])%12345; } cout<<f[n][0]; return 0; }
下面是输入n,输出x1~xn的c++程序: #include<iostream> using namespace std; int main() { int n,i,j,a[101]; cout<<"input n:"; //输入骨牌数 cin>>n; a[1]=1;a[2]=2; cout<<"x[1]="<<a[1]<<endl; cout<<"x[2]="<<a[2]<<endl; for (i=3;i<=n;i++) //递推过程 { a[i]=a[i-1]+a[i-2]; cout<<"x["<<i<<"]="<<a[i]<<endl; } } 下面是运行程序输入 n=30,输出的结果: input n: 30 x[1]=1 x[2]=2 x[3]=3 ........ x[29]=832040 x[30]=1346269

C语言入门必学—10个经典C语言算法

C语言入门必学—10个经典C语言算法

C语言入门必学—10个经典C语言算法C语言是一种广泛使用的编程语言,具有高效、灵活和易学的特点。

它不仅在软件开发中被广泛应用,也是计算机科学专业的必修课。

在学习C语言的过程中,掌握一些经典的算法是非常重要的。

本文将介绍10个经典C语言算法,帮助读者更好地了解和掌握C语言。

一、冒泡排序算法(Bubble Sort)冒泡排序算法是最简单、也是最经典的排序算法之一。

它通过不断比较相邻的元素并交换位置,将最大(或最小)的元素逐渐“冒泡”到数组的最后(或最前)位置。

二、选择排序算法(Selection Sort)选择排序算法是一种简单但低效的排序算法。

它通过不断选择最小(或最大)的元素,并与未排序部分的第一个元素进行交换,将最小(或最大)的元素逐渐交换到数组的前面(或后面)。

三、插入排序算法(Insertion Sort)插入排序算法是一种简单且高效的排序算法。

它通过将数组分为已排序和未排序两个部分,依次将未排序部分的元素插入到已排序部分的合适位置。

四、快速排序算法(Quick Sort)快速排序算法是一种高效的排序算法。

它采用了分治的思想,通过将数组分为较小和较大两部分,并递归地对两部分进行排序,最终达到整个数组有序的目的。

五、归并排序算法(Merge Sort)归并排序算法是一种高效的排序算法。

它采用了分治的思想,将数组一分为二,递归地对两个子数组进行排序,并将结果合并,最终得到有序的数组。

六、二分查找算法(Binary Search)二分查找算法是一种高效的查找算法。

它通过不断将查找范围折半,根据中间元素与目标值的大小关系,缩小查找范围,最终找到目标值所在的位置。

七、递归算法(Recursive Algorithm)递归算法是一种通过自我调用的方式解决问题的算法。

在C语言中,递归算法常用于解决树的遍历、问题分解等情况。

八、斐波那契数列算法(Fibonacci Sequence)斐波那契数列是一列数字,其中每个数字都是前两个数字的和。

04.递推算法(C++版包括习题参考答案)

04.递推算法(C++版包括习题参考答案)

【例6】过河卒(Noip2002) 【问题描述】 棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向 下、或者向右。同时在棋盘上的任一点有一个对方的马(如C点),该马 所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点 和P1,„„,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点 (0,0)、B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给 出的,C≠A且C≠B。现在要求你计算出卒从A点能够到达B点的路径的条数。
min{m , n}1 i 0
s 1=
(n i ) * (m i )
2.长方形和正方形的个数之和s 宽为1的长方形和正方形有m个,宽为2的长方形和正方形有 m-1个,┉┉,宽为m的长方形和正方形有1个; 长为1的长方形和正方形有n个,长为2的长方形和正方形有n1个,┉┉,长为n的长方形和正方形有1个; 根据乘法原理
【例3】棋盘格数
设有一个N*M方格的棋盘( l≤ N≤100,1≤M≤100)。求出该棋盘中包含有多少 个正方形、多少个长方形(不包括正方形)。 例如:当 N=2, M=3时: 正方形的个数有8个:即边长为1的正方形有6个;边长为2的正方形有2个。 长方形的个数有10个:即2*1的长方形有4个:1*2的长方形有3个:3*1的长 方形有2个:3*2的长方形有1个: 程序要求:输入:N,M 输出:正方形的个数与长方形的个数 如上例:输入:2 3 输出:8 10 【算法分析】 1.计算正方形的个数s1 边长为1的正方形个数为n*m 边长为2的正方形个数为(n-1)*(m-1) 边长为3的正方形个数为(n-2)*(m-2) ………… 边长为min{n,m}的正方形个数为(m-min{n,m}+1)*(n-min{n,m}+1) 根据加法原理得出

C语言-递推递归

C语言-递推递归

2012-3-20
12
伯努利装错信封问题
某人给不同地址不同姓名的n位朋友写信,信 某人给不同地址不同姓名的n位朋友写信, 信封都分别写好了。请问:所有信笺、 笺、信封都分别写好了。请问:所有信笺、 信封全都装错的情况有多少种? 信封全都装错的情况有多少种? 信封:A B 信封: 信笺: 信笺:a b C c D d E e F f … …
信封:A B C D E F … 信封: 信笺: 后 封也都装错 封也都装错) 信笺:b a (后n-2封也都装错
错误2: 错误 :
信封: 信封:A B C D E F … 信笺: 封也都装错) 信笺:b 非a (后n-2封也都装错 后 封也都装错
2012-3-20
装错情况 种数Sn-1
14
Sn= (n-1)(Sn-1+ Sn-2)
A B C
2012-3-2024 Nhomakorabea递归
• 当有n个盘子需要移动时,通常的方法如下: (1)把A柱上n-1个盘子借助C柱移动到B柱上。只有 这样,C柱才能为空,则A柱上的第n个盘子(最大 的那个)才能直接移动到C柱上。 (2)将A柱上的剩下的第n个盘子移动到C柱上。这个 盘子已最后到位,不需要再移动了。 (3)再将B柱上的n-1个盘子借助A柱移动到C柱。
2012-3-20 19
递归
f (1) = 1 n =1 f ( n) = f ( 2) = 1 n=2 f (n) = f (n − 2) + f (n − 1) n ≥ 3
int func(int n) /*求斐波那契数列的第n个数*/ { int result; if(n==1) result=1; else if(n==2) result=1; else result=func(n-1)+func(n-2); /*递归*/ return result; } 2012-3-20
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

参考题解
• 首先我们定义一个表pri[max],pri[i]表示第i个质数, 第一个质数为2.设数组max,其中max[i]记录i的最 大质因子。定义f(b,x1,x2)表示区间[x1,x2]之间不包 括大于第b个质数的质因子的所有正整数,则有如 下递归关系: F(b,x1,x2)=f(b-1,x1,x2)+f(b,(x1-1) div pri[b]+1,x2 div pri[b]) • 该递归式的边界条件为: • F=0 x1>x2 • F=x2-x1+1 x2<=pri[b] • 可直接验证 x1=x2 • F=trunc(log2(x2))-trunc(log2(x1)) b=1
例3:出栈序列统计
• 【问题描述】 • 栈是常用的一种数据结构,有n个元素在栈顶端一侧等待进 栈,栈顶端另一侧是出栈序列。你已经知道栈的操作有两种: push和pop,前者是将一个元素进栈,后者是将栈顶元素弹出。 现在要使用这两种操作,由一个操作序列可以得到一系列的输出 序列。请你编程求出对于给定的n,计算并输出由操作数序列1 ,2,…,n,经过一系列操作可能得到的输出序列总数。 • 【输入】 【输出】 • 就一个数n(1≤n≤1000)。 一个数,即可能输出序列的总数目。 • 【样例】 • stack.in stack.out • 3 5
• 答案为f[n],时间复杂度为O(n)。
方法二
• 对于i>=3,分析第一列的两个格子覆盖情况,有两种情 况: 1.用1*2的骨牌竖着覆盖第一列,这种情况的方案数等 于后面2*(i-1)的长方形的覆盖方案数,即f[i-1];
2.用两个1*2的骨牌横着覆盖,这种情况的方案数等于 后面2*(i-2)的长方形的覆盖方案数,即f[i-2]。
【算法分析】
• C(2n,n)/(n+1) • =2n*(2n-1)*(2n-2)…*(n+1)/n!/(n+1) • =2n*(2n-1)*(2n-2)*…*(n+2)/n!。 • 考虑到这个数据可能比较大,所以用高精度 运算来计算这个结果。 • 本题实际是一个经典的Catalan数模型。有关 Catalan数的详细解释请参考《组合数学》等书 。
方法二
• 当k达到106的时候,方法一会超时。 • 由于10007是素数,在计算C(k,n)mod 10007时可以采用扩展GCD来解决。 • 时间复杂度为O(k)。
参考代码:
#include <iostream> #include <fstream> using namespace std; ifstream fin("factor.in"); ofstream fout("factor.out"); const int MAXN=1005; int dp[MAXN][MAXN],a,b,k,n,m,ans;
例2:B光滑数
• 【问题描述】 • B为一个正整数,如果一个自然数N的质因子分解式中没有大于B的因子, 我们就称N是一个B光滑数。请你编一个程序,求出某个区间中所有的B光 滑数的个数。 • 输入: • 输入文件名为bnum.in,仅有一行,包含三个用空格隔开的整数N,M,B,其 中1<=N<=2,000,000,000,1<=M<=100,000,000,1<=B<=1,000 ,000。 • 输出:输出文件名为bnum.out,仅一行。一个整数,表示区间[N,N+M]之 间的B光滑数的个数。 • 【样例输入】 • 30 10 5 • 【样例输出】 • 4
【思考与提高】
【思考与提高】
再设f(a,b)为从状态(a,b)通过移动火车变为状态(0,0) 的所有移动方法。类似于动态规划的状态转移方程,我 们可写出以下递归式:
边界值:f(0,0)=1。 有了这个递归公式后,再写程序就比较简单了。
例4:骨牌覆盖问题
• 有2行n列的长方形方格,要求用n个1*2的 骨牌铺满。有多少种铺法? • 如n=3时有以下3种覆盖方法:
递推算法
确定状态 确定递推关系和边界条件
day2)
• 【题目描述】给定一个多项式(ax+by)k,请求出多项式展 开后xnym项的系数 • 【输入】共一行,包含5个整数,分别为a,b,k,n,m,每 两个整数之间用一个空格隔开。 • 【输出】输出共1行,包含一个整数,表示所求的系数 ,这个系数可能很大,输出对10007 取模后的结果。 • 【输入输出样例】 factor.in factor.out 11312 3 • 【数据范围】 对于 30%的数据,有0≤k≤10; 对于 50%的数据,有a = 1,b = 1; 对于 100%的数据,有0≤k≤1,000,0≤n, m≤k, 且n + m = k,0≤a,b≤1,000,000。
int main() { fin>>a>>b>>k>>n>>m;
dp[1][1]=dp[1][2]=1; for (int i=2;i<=k;i++) for (int j=1;j<=i+1;j++) dp[i][j] = (dp[i-1][j] + dp[i-1][j-1]) % 10007; ans = dp[k][m+1];
【思考与提高】
我们知道,在某个状态下,所能做的操作(移动方法)无非 有两种: (1)将右方的等待进栈的第一个元素进栈; (2) 将栈顶的元素出栈,进入左边的出栈序列。 设此时右方、栈、左方的元素个数分别为a,b,c。我 们就能用(a,b,c)表示出当前的状态。显然n=a+b+c,则 c=n-a-b。即已知a和b,c就被确定,所以我们可以用(a,b) 来作为状态的表示方法。则起始状态为(n,0),目标状态为 (0,0)。 又由上面的两种移动方法,我们可类似的得到两种状 态转移方式:
参考程序: #include <iostream>
#include <cstdio> using namespace std; typedef long long lld; lld i,n,ans; lld h[1000]; int main() { freopen ("stack.in","r",stdin); freopen ("stack.out","w",stdout); h[2]=1; cin>>n; n=n+2; for (lld i=3;i<=n;i++) for (lld k=2;k<i;k++) h[i]=h[i]+h[k]*h[i-k+1]; cout<<h[n]<<endl; return 0; }
方法一
• 状态:f[i]表示铺满2*i的长方形的方案数 • 找规律,手工或搜索求出i=1,2,3,4,5的方案数 分别为1,2,3,5,8,容易发现 f[i]=f[i-1]+f[i-2](i>=3) • 边界条件:f[1]=1,f[2]=2 • 递推关系式 • 1 i=1 • f[i]= 2 i=2 f[i-1]+f[i-2] i>=3
方法一
• 根据二项式定理可知: k k i k i k i i i i k i i k * * * * *x * y C (ax+by) = = k (ax) (by) C k a b i 0 i 0 n n m n m • 取i=n,x y 的系数为 C k * a * b • 其中an和bm可以用快速幂来计算,在lg(n)+lg(m)内完成。 n • 计算 C k 可以用递推来求解。 • 状态:f[i,j]表示从i个数中选j个数的方案数。f[k,n]就是答案。 • 根据第i数选还是不选来进行分析: 1.选择第i个数:此情况的方案数等价于从i-1个数中选择j-1个 数的方案数即f[i-1,j-1]; 2.不选第i个数:此情况的方案数等价于从i-1个数中选择j个数 的方案数即f[i-1,j] 所以f[i,j]=f[i-1,j-1]+f[i-1,j] • 边界条件:f[i,0]=1,f[i,i]=1。 时间复杂度为O(n*k)。
方法四
• 分治,一分为二来考虑,左边为n div 2列, 右边为n-n div 2列,如果左右独立则方案数 为f[n div 2]*f[n-n div 2],如果有横向覆盖第n div 2列和第n div 2+1列,则方案数为f[n div 2-1]*f[n-n div 2-1] • 所以f[n]= f[n div 2]*f[n-n div 2]+f[n div 21]*f[n-n div 2-1]
所以f[i]=f[i-1]+f[i-2]
方法三
• 分析用1*2的骨牌覆盖列的位置来计算方案数 • 1.如果i为偶数,覆盖方案分为两类: (1)没有竖立覆盖其中一列的情况:全部用横向覆盖的方 案,方案数为1; (2)有竖立覆盖的情况:为了避免重复,考虑第一次竖立 覆盖的位置在x列,x必须是奇数,而且前1到x-1列覆盖方 法唯一,全部采用横向覆盖,方案数等于后面i-x列的覆盖 情况,即f[i-x]。 • 所以当i为偶数时,f[i]=1+f[1]+f[3]+...+f[i-3]+f[i-1] • 2.如果i是奇数,一定有竖立覆盖的情况, f[i]=1+f[2]+f[4]+.....+f[i-3]+f[i-1] • 如何证明该递推关系式等价于f[i]=f[i-1]+f[i-2]? • 试着用横向覆盖的来分析递推关系式。
【算法分析】
• 我们通过回溯的方法计算并输出不同的出栈序列,这里只 要求输出不同的出栈序列总数目,所以我们希望能找出相 应的递推公式进行处理。 • 从排列组合的数学知识可以对此类问题加以解决。 • 我们先对n个元素在出栈前可能的位置进行分析,它们 有n个等待进栈的位置,全部进栈后在栈里也占n个位置, 也就是说n个元素在出栈前最多可能分布在2*n位置上。 • 出栈序列其实是从这2n个位置上选择n个位置进行组合 ,根据组合的原理,从2n个位置选n个,有C(2n,n)个。但 是这里不同的是有许多情况是重复的,每次始终有n个连 续的空位置,n个连续的空位置在2n个位置里有n+1种, 所以重复了n+1次。所以出栈序列的种类数目为:
相关文档
最新文档