拆分自然数N之和
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【拆分自然数N之和】
任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。(n<=100)
【样例】
输入n=7
输出:
7=1+6
7=1+1+5
7=1+1+1+4
7=1+1+1+1+3
7=1+1+1+1+1+2
7=1+1+1+1+1+1+1
7=1+1+1+2+2
7=1+1+2+3
7=1+2+4
7=1+2+2+2
7=1+3+3
7=2+5
7=2+2+3
7=3+4
【分析过程】:
1.10=3+7与10=7+3 是同一个拆分。(避免重复,只要让前面的加数≤后面的加数)
2.n=7.
第一步,将N拆分为2项之和:
7=1+6
7=2+5
7=3+4
(不能拆)
其中对它进行继续拆分
.
【如何用算法实现】
用数组a[0..100],a[k]中存储已完成的一种拆分。比如:7=1+6。可以用数组a表示:a[0]=7,a[1]=1,a[2]=6,k=2,继续拆分从a[k](从a[2] 开始);a[k]能否再次拆分取决于a[k] div 2 是否大于或等于a[k-1];在这里,我们采取的回溯(递归)过程中有两个元素:nx表示要拆分的数值大小,kx表示接着要拆的那个数的下标,nx存储在数组元素a[kx]中,即a[kx]=nx。
参考程序:
var
n,i,j:integer;
a:array[0..100] of integer;
procedure sum(nx,kx:integer);
var
k,m,l:integer;
begin
j:=j+1;
write('Sum No.',j:3,':',a[0],'='); {输出标头,可以根据题目具体要求删或修改}
for k:=1 to kx-1 do
write(a[k],'+'); {输出前面的加数}
writeln(a[kx]); {输出最后一个加数并换行}
k:=kx;//保存当前要拆分数的下标
l:=a[k]; {第一组拆分结束,l是替身,后面要计算相差部分}
for m:=a[k-1] to l div 2 do {新赋值的拆分范围,因为不能大于前一个加数,所以初值是前一个加数}
begin
a[k]:=m;
a[k+1]:=l-m; {新赋值初始化拆分}
sum(a[k+1],k+1); {回溯下一个}
end;
end;
begin
read(a[0]);
j:=0;
if a[0]>=2 then {a[0]>=2时才有数据可以拆分}
for i:=1 to a[0] div 2 do {第一个加数的拆分范围}
begin
a[1]:=i;
a[2]:=a[0]-a[1]; {初始化拆分}
sum(a[0],2); {调用sum}
end; {when a[0]>2}
writeln;
end.