习题3
3-1 递推求解b数列 已知b数列定义:
b1?1,b2?2,bn?3bn?1?bn?2(n?2)
递推求b数列的第20项与前20项之和。 解:
#include
{ int k,n; long b[3000],s; printf(\请输入n: \ scanf(\ b[1]=1;b[2]=2;s=3; for(k=3;k<=n;k++)
{ b[k]=3*b[k-1]-b[k-2];
s+=b[k]; }
printf(\ printf(\ }
3-2 双关系递推数列 集合M定义如下: 1)1?M
2)x?M?2x?1?M,3x?1?M
3)再无别的数属于M
试求集合M元素从小到大排列的第2011个元素与前2011 个元素之和。 解:(1)设计要点
设n个数在数组m中,2x+1与3x+1均作为一个队列,从两队列中选一排头(数值较小者)送入数组m中。所谓“排头”就是队列中尚未选入m的最小的数(下标)。这里用p2表示2x+1这一列的排头的下标,用p3表示3x+1这一列的排头的下标。
if(2*m(p2)<3*m(p3))
{ m(i)=2*m(p2)+1;p2++;} if(2*m(p2)>3*m(p3))
{ m(i)=3*m(p3)+1;p3++;}
特别注意:两队列若出现相等时,给m数组赋值后,两排头都要增1。
if(2*m(p2)==3*m(p3)) { m(i)=2*m(p2)+1;
p2++; p3++; // 为避免重复项,P2,p3均须增1
} (2) 程序设计 // 双关系递推 #include
{int n,p2,p3,i;long s,m[3000]; m[1]=1;s=1;
p2=1;p3=1; // 排头p2,p3赋初值 printf(\请输入n: \ scanf(\ for(i=2;i<=n;i++) if(2*m[p2]<3*m[p3])
{ m[i]=2*m[p2]+1; s+=m[i];
p2++; }
else
{ m[i]=3*m[p3]+1; s+=m[i];
if(2*m[p2]==3*m[p3]) p2++; // 为避免重复项,P2须增1 p3++;
}
printf(\ printf(\ }
3-3 多幂序列
设x,y,z为非负整数,试计算集合
M?{2x,3y,5z|x?0,y?0,z?0}
的元素由小到大排列的多幂序列第n项与前n项之和。 (1)递推算法设计
集合由2的幂、3的幂与5的幂组成,实际上给出的是3个递推关系。 显然,第1项也是最小项为1(当x=y=z=0时)。 从第2项开始,为了实现从小到大排列,设置3个变量a,b,c,a为2的幂,b为3的幂,c为5的幂,显然a,b,c互不相等。
设置k循环(k=2,3,…,n,其中n为键盘输入整数),在k循环外赋初值:a=2;b=3;c=5;s=1;
在k循环中通过比较赋值:
当a
当b 当c 递推过程描述: a=2;b=3;c=5; // 为递推变量a,b,c赋初值 for(k=2;k<=n;k++) { if(a { f[k]=a;a=a*2;} // 用a给f[k]赋值 else if(b { f[k]=b;b=b*3;} // 用b给f[k]赋值 else { f[k]=c;c=c*5;} // 用c给f[k]赋值 } 在这一算法中,变量a,b,c是变化的,分别代表2的幂、3的幂与5的幂。 上述递推算法的时间复杂度与空间复杂度均为O(n)。 (2)多幂序列程序实现 // 多幂序列求解 #include {int k,m,t,p2,p3,p5; double a,b,c,s,f[100]; printf(\求数列的第m项与前m项和,请输入m: \ scanf(\ f[1]=1;p2=0;p3=0;p5=0; a=2;b=3;c=5;s=1; for(k=2;k<=m;k++) { if(a { f[k]=a;a=a*2; // 用2的幂给f[k]赋值 t=2;p2++; // t=2表示2的幂,p2为指数 } else if(b { f[k]=b;b=b*3; // 用3的幂给f[k]赋值 t=3;p3++; // t=3表示3的幂,p3为指数 } else { f[k]=c;c=c*5; // 用5的幂给f[k]赋值 t=3;p5++; // t=5表示5的幂,p5为指数 } s+=f[k]; } printf(\数列的第%d项为: %.0f \ if(t==2) // 对输出项进行标注 printf(\ else if(t==3) printf(\ else printf(\ printf(\数列的前%d项之和为:%.0f \\n\} 3-4 双幂积序列的和 由集合M?{2x3y|x?0,y?0}元素组成的复合幂序列,求复合幂序列的指数和x+y≤n(正整数n从键盘输入)的各项之和 s?x?y?0?23xny,x?0,y?0 (1)设计要点 归纳求和递推关系: 当x+y=0时,s(1)=1; 当x+y=1时,s(1)=2+3; 222 当x+y=2时,s(2)=2+2×3+3=2*s(1)+ 3 32233 当x+y=3时,s(3)=2+2×3+2×3+3=2*s(2)+ 3 k 一般地,当x+y=k时,s(k)=2*s(k?1)+3 即有递推关系: s(k)=2*s(k)+3k k 其中3可以通过变量迭代实现。这样可以省略数组,简化为一重循环实现复合幂序列求和。 (2)程序实现 // 复合幂序列求和 #include {int k,n; long sum,t,s[100]; printf(\请输入幂指数和至多为n:\ scanf(\ t=1;s[0]=1; sum=1; for(k=1;k<=n;k++) {t=t*3; // 迭代得t=3^k s[k]=2*s[k-1]+t; // 实施递推 sum=sum+s[k]; } printf(\幂指数和至多为%d的幂序列之和为:%ld\\n\} 3-5 粒子裂变 核反应堆中有α和β两种粒子,每秒钟内一个α粒子可以裂变为3个β粒子,而一个β粒子可以裂变为1个α粒子和2个β粒子。若在t=0时刻的反应堆中只有一个α粒子,求在t秒时反应堆裂变产生的α粒子和β粒子数。 1. 算法设计 设在t秒时α粒子数为f(t),β粒子数为g(t),依题可知: g(t)=3f(t-1)+2g(t-1) (1) f(t)=g(t-1) (2) g(0)=0,f(0)=1 由(2)得f(t-1)=g(t-2) (3) 将式(3)代入(1)得 g(t)=2g(t-1)+3g(t-2) (t≥2) (4) g(0)=0,g(1)=3 (5) 以递推关系(4)与初始条件(5)完成递推。 2.粒子裂变C程序设计 // 粒子裂变 #include {int t,k;long g[100]; printf(\ scanf(\ g[0]=0; g[1]=3; // 确定初始条件 for(k=2;k<=t;k++) g[k]=2*g[k-1]+3*g[k-2]; // 完成递推 printf(\秒时反应堆中β粒子数为:%ld \\n\ printf(\秒时反应堆中α粒子数为:%ld \\n\} 3-6 m行n列逆转矩阵