论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > C语言程序设计教程
Tag:新手,函数,指针,数据类型,对象,Turbo,入门,运算符,数组,结构,二级,,tc,游戏,试题,问答,编译,视频教程

C程序设计例解(02)

文章类别:C语言程序设计 | 发表日期:2008-9-24 14:47:04

02.找一个最小的自然数x,使它等于不同的两对自然数的三次幂之和,即使得:
        x=a*a*a+b*b*b=c*c*c+d*d*d
    其中a,b,c,d都是自然数,且有a!=c和a!=d
解:
    问题要找的解是两个自然数对,以自然数对为解的候选者,如程序能这样枚举解的候选者,使枚举出来的自然数对的三次幂之和构成一个不减的序列,则当发现两个自然数对的三次幂之和相等时,这两对自然数就是问题的解。将这种思想写成抽象算法描述如下:
{
    i1=1;j1=1;x=i1*i1*i1+j1*j1*j1;
    do
    {
        i0=i1;j0=j1;min=x;    /*保存上一个解的候选者*/
        确定下一对自然数i1,j1;
        x=i1*i1*i1+j1*j1*j1;
    }while(x!=min);
    printf("%d=%d^3+%d^3=%d^3+%d^3\n",x,i0,j0,i1,j1);
}
问题已转化成如何按上述要求逐一自然数对。
    为了寻找产生候选者规则的线索,将问题简化为找一个最小的自然数x,使它等于不同的两对自然数的平方之和。下面列出部分两个自然数的平方之和的数表s[],其中:
    s[i][j]=i*i+j*j


从上面的s[]表查得:
    50=1*1+7*7=5*5+5*5
    65=1*1+8*8=4*4+7*7
所以50是两对自然 平方和的最小者。要寻找的产生候选者的规则就是要寻找一个方法,使枚举产生的候选者(自然数对)的平方和构成以下数列:
    2  5  8  10  13 ... 45  50  50
    仔细考查表中s[i][j]与i和j,不难发现有以下性质:
1) s[i][j]>s[i][k],对于所有的i,当j>k
2) s[i][j]>s[k][j],对于所有的j,当i>k
3)s[i][j]=s[j][i]
    因问题将自然数对(i,j)和(j,i)视为同一个自然数对,所以只需考虑i>=j的情况,性质1)说明对于表中的每一行,应从左到右逐个考查,且没有必要保存一整行的候选者供选择,一行只要保存一个已足够。当某行的当前候选者已被确认不是解时,则可生成该行的下一个候选者,等候被考虑。
    由以上分析,可用下面的两个一维数组表示当前正在考虑的状态:
    int s[?],j[?];
其中?意指数组的大小还未确定。数组j[]的成份j[k]表示s表中的第k行当前待考虑的列号。所以,s[]和j[]有关系:
    s[k]=k*k*k+j[k]*j[k]*j[k]
    将以上分析结果反映到找解方法中,原先的找解算法可改写成如下形式:
{
    for(k=1;k<?;k++)
    {  /*每行都从第一列一始考查*/
        j[k]=1;
        s[k]=k*k*k+1;
    }
    i=1;   /*最初候选者在第一行*/
    do
    {
        min=s[i];i0=i;j0=j[i];
        为i行设定下一个候选者存入s[i];
        在s[]中找最小的候选者为正式候选者,并将找到的位置存于i中;
    }while(s[i]!=min);
    printf("%d=%d^3+%d^3=%d^3+%d^3\n",min,i0,j0,i,j[i]);
}
按上述算法编写程序还有两处不足,需进一步确定或调整:一是为个数不确定的数组s[]和j[]送初值;另一个是个数不确定的候选者中选正式候选者。由性持,由性质2),引入当前考虑的行的范围,最大行ih和最小行il,其中ih是指有j[k]为1的最小下标k,因为当前还不可能在ih行之后选到最小的s[i],所以置初值和选最小元可局限于k<=ih的s[k]中进行。另外,当j[i]=i时,因对s表的考查只限于它的左下角,所以对该行的进一步考查应放弃。利用这个事实,程序可引入il表示s表的当前行范围的下界。于是置初值、寻找局限于s表的il 行到 ih行之间。每当j[i]=i时,il增1;每当j[i]=1时,ih增1,并同时设定s[ih]和j[ih]的初值。
    再次把上述思想反映到算法中,找解算法又可改写成如下形式:
算法--找一个最小的自然数x,使它等于不同的两对自然 的三次幂之和
{
    il=1;ih=1;    /*首先只局限于第一行*/
    j[1]=1;s[1]=2;i=1;
    do
    {
        min=s[i];i0=i;j0=j[i];
        if(j[i]==1)
        {   /*调整ih,并为j[ih]与s[ih]设定初值*/
            ih++;
            j[ih]=1;
            s[ih]=ih*ih*ih+1;
        }
        if(j[i]==i)il++;        /*调整il*/
        else
        {   /*为i行设定下一个待候选者*/
            j[i]++;
            s[i]=i*i*i+j[i]*j[i]*j[i];
        }
        /*以下确定新的i,使得s[i]=min(s[il],...s[ih])*/
        i=il;
        for(k=il+1;k<=ih;k++)
            if(s[k]<s[i])i=k;
    }while(s[i]!=min(;
    printf("%d=%d^3+%d^3=%d^3+%d^3\n",min,i0,j0,i,j[i]);
}
以上算法可作为最后的算法,下面的程序作了必要的优化,避免反复计算一个整数的三次幂。引入数组p[],其中p[i]存储i*i*i。

程序代码如下:

#include<stdio.h>
#define N 50
void main()
{
    int i,il,ih,i0,j0,min,k;
    int j[N],s{n],p[N];
    il=1;ih=1;j[1]=1;
    p[1]=1;s[1]=2;i=1;
    do
    {
        min=s[i];i0=i;j0=j[i];
        if(j[i]==1)
        {
            ih++;p[ih]=ih*ih*ih;
            j[ih]=1;s[ih]=p[ih]+1;
        }
        if(j[i]==i) il++;
        else{
            j[i]++;
            s[i]=p[i]+p[j[i>;
        }
        i=il;
        for(k=il+1;k<=ih;k++)
            if(s[k]<s[i]) i=k;
    }while(s[i]!=min&&ih!=N);
    if(s[i]==min)
        printf("%d=%d^3+%d^3=%d^3+%d^3\n",min,i0,j0,i,j[i]);
    else printf("The %d is too small.\n",N);
}

程序运行结果如下:

1729=10^3+9^3=12^3+1^3
上一篇:{应用}C程序设计例解(01) 人气:5031
下一篇:{应用}C程序设计例解(03) 人气:4963
视频教程列表
文章教程搜索
 
C语言程序设计推荐教程
C语言程序设计热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058