利用数学归纳法进行问题验证与拓展:一个自然数N的立方等于N个连续奇数之和


前言

前些日子为重庆邮电大学复试笔试做准备,无意间刷到了某年真题里的一道算法题:
问题验证:一个自然数N的立方等于N个连续奇数之和
翻看了CSDN上一些博主的代码和思路,发现许多博主使用了最为费时费力的方法,时间复杂度竟然高达O(n^3)的数量级。因此我决定利用一种数学归纳法去提升问题的效率同时将自然数的限制扩展到任意整数。


一、思路是什么?

在讲解思路之前我先举几个简单的例子:
3^3 = 7+9+11
4^3 = 13+15(16-1)+17(16+1)+19
5^3 = 21+23+25+27+29
我们能否快速的发现,任意自然数N的立方,都可以由N的平方向两端对称展开的连续奇数和所得到,因此我们能够联想到一种更高效的方法——找开端
根据对称性,我们可以知道连续奇数序列的两端距离N的平方长度均为N/2,因此我们可以先通过N^2-(+)N/2找到数列的左端(右端),然后稍微调整一下开始端,使其满足奇数。随后开始逐2累加即可。

同时这种方法对于负数的立方问题也能够有效的验证,只需调整开端位置即可。

二、代码运行演示

1.代码

代码如下:

#include<stdio.h>
#include<math.h>
/*
思路:
	由数学归纳法可推得任意 n^3 都可以由 n^2 向两端拓展的连续奇数累加求和所得
	例如 5^3 = 29+27+25+23+21  其中 5^2 = 25
	例如 4^3 = 19+17+15+13     其中 4^2 = 16
	因此计算出开始端奇数并开始向后逐个累加即可
*/
void main() {
	//定义变量n
	int n;
	//输入变量n取值(n为任意整数)
	printf("please input your numbers: ");
	scanf("%d", &n);
	if (n == 0) {
		printf("(0)*(0)*(0)=(0)"); 
		return;
	}
	//确定向两端奇数展开的中间数double_sum
	int double_sum;
	if (n > 0) double_sum = n * n;
	if (n < 0) double_sum = -1 * n * n;
	//由递增数列对称性求得开始端奇数start
	int start; 
	if (n > 0) start = double_sum - 2 * (n / 2);
	else start = double_sum + 2 * (n / 2);
	if (start % 2 == 0) start++;

	printf("奇数和从:%d 开始累加...\n",start);
	printf("(%d)*(%d)*(%d) = ", n, n, n);
	//开始逐项累加,累加次数为 n 次
	for (int i = start, j = 0; j < abs(n); j++, i += 2) {
		if (j == abs(n)-1) printf("(%d)\n", i);
		else printf("(%d)+", i);
	}

	return;
}

2.测试样例

在这里插入图片描述


总结

相较于三层for循环暴力搜索的方法,利用数学归纳法能够将该问题时间规模压缩至O(n),即高效也简单,同时也扩展了该问题的适用范围,不再局限于自然数而是打开了负数的大门。
如果代码有瑕疵请及时指正,深表感谢。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值