C语言-尼科彻斯定理

来源:互联网 发布:成都知创科技有限公司 编辑:程序博客网 时间:2024/05/16 07:10

尼科彻斯定理:任何一个整数的立方都可以写成一串连续奇数的和.例如:

1的立方=1

2的立方=3+5

3的立方=7+9+11

4的立方=13+15+17+19


下面通过几个方案实现一下,具体代码如下:

#include <stdio.h>int main(int argc, const char * argv[]) {        int n;    printf("请输入一个正整数:");    scanf("%d",&n);        methodOne(n);    methodTwo(n);    methodThree(n);        /*     请输入一个正整数:3     3*3*3=27=7+9+11YES     27=7+9+...+11     3*3*3=27=11+9+7     */    return 0;}

函数1功能实现思路:使用等差数列


问题分析与算法设计:本题是一个定理,我们先来证明它是成立的。对于任一正整数a,不论a是奇数还是偶数,整数(a×a-a+1)必然为奇数。那么可以构造一个等差数列,数列的首项为(a×a-a+1),等差数列的差值为2(奇数数列),则前a项的和为:


a×((a×a-a+1))+2×a(a-1)/2

=a×a×a-a×a+a+a×a-a

=a×a×a


定理成立。通过定理的证明过程可知所要求的奇数数列的首项为(a×a-a+1),长度为a。编程的算法不需要特殊设计,可按照定理的证明过直接进行验证。


等差数列是常见数列的一种,如果一个数列从第二项起,每一项与它的前一项的差等于同一个常数,这个数列就叫做等差数列,而这个常数叫做等差数列的公差,公差常用字母d表示。

例如:1,3,5,7,9……2n-1

通项公式为:an=a1+(n-1)*d。首项a1=1,公差d=2

n项和公式为:Sn=a1*n+[n*(n-1)*d]/2Sn=[n*(a1+an)]/2

注意:以上n均属于正整数。

void methodOne(int n){        int b,c,d;    b = n*n*n;    printf("%d*%d*%d=%d=",n,n,n,b);        //输出数列,首项为n*n-n+1,等差值为2    //注意一个问题,输入正整数几,即有几个连续数字相加求和,所以这里遍历a次,在首选项的基础上,每次相对前一个值加上公差即可    //如:3的三次方=7+9+11,即首选项为7,公差为2,第一次7+0,第二次7+2,第三次7+4    for (d=0,c=0; c<n; c++) {        d += (n*n-n+1)+(c*2); //求数列的前a项的和        printf(c?"+%d":"%d",(n*n-n+1)+(c*2));    }        if (d==b) {//若条件满足则输出YES        printf("YES\n");    }else{        printf("NO\n");    }}

函数2功能实现思路:先计算输入数的立方,然后从1开始累计和,累计每次加2保证下个数也为奇数,如果累加和大于立方数时,跳出本次循环。进行下一次的尝试。当找到后,记录开始位置,结束位置。

void methodTwo(int n){    int max = n*n*n;    int i,j,sum = 0;    for(i=1; i<max; i=i+2){        for(j=i; j<max; j=j+2){            sum += j;            if(sum == max){                printf("%d=%d+%d+...+%d\n",max,i,i+2,j);                return;            }                        if(sum > max){                sum = 0;                break;            }        }    }}

函数3功能实现思路:


任何立方值(这里设为sum)的一半(这里设置为x)如果为奇数,则x+x+2,一定大于sum,那么这串连续期数的最大值不会超过x,如果x是偶数,需把它变成奇数,那么变成奇数到底是加1、减1还是其他呢?这里选择加1,因为x+1+x-1正好等于sum,所以当x是偶数时,这串连续奇数的最大值不会超过x+1,在确定了范围之后就可以从最大值开始进行穷举。

void methodThree(int n){        int i,k = 0,l,m,sum,flag = 1;    m = n * n * n; //计算出输入数的立方    i = m / 2;        //当i为偶数时,i的值加1    if (i % 2 == 0) { i += 1;}        while (flag == 1 && i >= 1) {        sum = 0;        k = 0;        while (1) {            sum += (i - 2*k); //奇数累加求和            k++;            if(sum == m){                printf("%d*%d*%d=%d=",n,n,n,m);                for (l = 0; l < k-1; l++) printf("%d+",i - l*2);                printf("%d\n",i - (k-1)*2); //输出累加求和的最后一个数                flag = 0;                break;            }            if (sum > m) break;        }        i -= 2; //i等于下一个奇数继续循环    }}

分析:程序中使用了两个while循环,第一个while循环语句功能是从可能的最大值开始直到1为止进行穷举,第二个while循环的功能是通过第一个while循环所确定的i值进行每次减2逐次累加求和,当累加和等于立方值时输出累加过程并跳出循环,当累加和大于立方值时也同样跳出第二个循环回到第一个循环中。



0 0