C语言初步-第39讲:问题求解——求素数(练习综合)

来源:互联网 发布:数据使用承诺书 编辑:程序博客网 时间:2024/06/03 21:58

任务和代码:

/**Copyright (c)2017 CSDN学院*All rights reserved*文件名称:main.c*作者: Osseyda完成日期:2017.9.27*版本号:v2.**问题描述:一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3,再如8的因子和是7(即1+2+4),8不是完数。          (1)输入一个数n,判断n是否是完数          (2)输出1000以内的所有完数*问题输出:输出1000以内的所有完数*/#include <stdio.h>int main(){    int i,m,total,is_complete,n=0;    for(m=1;m<=1000;m++){        is_complete=1;        total=0;        for(i=1;i<m;i++){            if(m%i==0)                total+=i;        }        if(m!=total){            is_complete=0;        }        if(is_complete==1){            printf("%d\t",m);            n++;            if(n%5==0)                printf("\n");        }    }    return 0;}
运行结果:



/*问题描述:亲密数:如果整数A的全部因子(包括1,不包括A本身)之和等于B;且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。求3000以内的全部亲密数。*问题输出:输出3000以内的全部亲密数。*/#include <stdio.h>int main(){    int m,i,j,a,b;    for(m=1;m<=3000;m++){        a=0,b=0;        for(i=1;i<m;i++){            if(m%i==0)                a+=i;    //a是m的因子和        }        for(j=1;j<a;j++){            if(a%j==0)                b+=j;    //b是a的因子和        }        if(b-m==0&&a!=m){         //若b=m,则a和m互为亲密数            printf("a=%d,其因子和为%d\t",m,a);            printf("b=%d,其因子和为%d\t",a,m);            printf("故a和b是一对亲密数\n");        }    }    return 0;}
运行结果:



/*问题描述:求满足条件n=a!+b!+c!的所有三位数n,其中a,b,c分别为n的百、十、个位数。*问题输出:输出满足条件n=a!+b!+c!的所有三位数n.*/#include <stdio.h>int main(){    int n,a,b,c,i,fa,fb,fc;    for(n=100;n<1000;n++){        c=n%10;        b=(n/10)%10;        a=n/100;        fa=1,fb=1,fc=1;        for(i=1;i<=a;i++)            fa*=i;        for(i=1;i<=b;i++)            fb*=i;        for(i=1;i<=c;i ++)            fc*=i;        if(n-fa-fb-fc==0)            printf("%d\t",n);    }    return 0;}

如果不是三位数呢?(由求阿姆斯特朗数联想到另一种解法)

#include <stdio.h>int main(){    int n,m,k,i,fact,sfact;    for(n=100;n<1000;n++){        k=n;        sfact=0;        while(k!=0){            m=k%10;            k/=10;            fact=1;            for(i=1;i<=m;i++)                fact*=i;            sfact+=fact;        }        if(n==sfact)            printf("%d\t",n);    }    return 0;}
运行结果:



/*问题描述:输入一个正整数,输出它的反序数(反序数,即将其所有位的数字反过来。例如,123是321的反序数)*问题输出:输出1000000以内的正整数n,要求9n是n的反序数。*/#include <stdio.h>int main(){    long n,m,k;    for(n=1;n<=1e6;n++){    //n的反序数是m        k=n;        m=0;        while(k!=0){            m=m*10+k%10;    //m进一位并加上余数            k/=10;        }        if(m==9*n)            printf("%ld的反序数是%ld\t",n,m);    }    return 0;}
运行结果:



/*问题描述:输入一个正整数,判断其是否为一个回文数(例1221、12321都是回文数,正着看、倒着看,是同一个数)。*问题输出:输出10000以内的所有回文数。*/#include <stdio.h>int main(){    int n,m,k,i=0;    for(n=1;n<=1e4;n++){    //n的反序数是m        k=n;        m=0;        while(k!=0){            m=m*10+k%10;    //m进一位并加上余数            k/=10;        }        if(m==n){           //两个反序数相等就是回文数            printf("%d\t",n,m);            i++;            if(i%8==0)                printf("\n");        }    }    return 0;}

运行结果:



/*问题描述:如果一个正整数等于其各个数字的立方和,则称该数为阿姆斯特朗数(亦称为自恋性数)。如 407=43+03+73就是一个阿姆斯特朗数*问题输出:输出1000以内的所有阿姆斯特朗数。*/#include <stdio.h>int main(){    int n,m,k,total;    for(n=1;n<=1e3;n++){        k=n;        total=0;        while(k!=0){            m=k%10;            k/=10;            total+=m*m*m;        }        if(n==total)            printf("%d\t",n);    }    return 0;}
运行结果:



/*问题描述:很有趣的一个题目:2011年11月02日是一个回文日:2011 1102,在2011级同学做这道题时我们刚刚度过这一天!请列出本世纪有多少个回文日。*问题输出:输出本世纪所有的回文日。*/#include <stdio.h>int main(){    int year,month,day,fy,by,hm,hd,hfy,hby;    for(year=2000;year<2100;year++){        fy=year/100,by=year%100;        hfy=(fy%10)*10+(fy/10);        hby=(by%10)*10+(by/10);        for(month=1;month<=12;month++){            hm=(month%10)*10+(month/10);            switch (month){                case 1:                case 3:                case 5:                case 7:                case 8:                case 10:                case 12:                    for(day=1;day<=31;day++){                        hd=(day%10)*10+(day/10);                        if(hd==fy&&hm==by&&hby==month&&hfy==day)                            printf("%d %d %d\n",year,month,day);                    }                    break;                case 4:                case 6:                case 9:                case 11:                    for(day=1;day<=30;day++){                        hd=(day%10)*10+(day/10);                        if(hd==fy&&hm==by&&hby==month&&hfy==day)                            printf("%d %d %d\n",year,month,day);                    }                    break;                case 2:                    if(year%4==0&&year%100!=0||year%400==0){                        for(day=1;day<=29;day++){                            hd=(day%10)*10+(day/10);                        if(hd==fy&&hm==by&&hby==month&&hfy==day)                            printf("%d %d %d\n",year,month,day);                        }                    }                    else                        for(day=1;day<=28;day++){                            hd=(day%10)*10+(day/10);                        if(hd==fy&&hm==by&&hby==month&&hfy==day)                            printf("%d %d %d\n",year,month,day);                        }            }        }    }    return 0;}

经过观察,如果年份的反序数就是月日的话,则ymd就是一个回文日,故另一种解法如下:

#include <stdio.h>int main(){    int year,month,day,hy,k;    for(year=2000;year<2100;year++){        k=year;        hy=0;        while(k!=0){            hy=hy*10+k%10;            k/=10;        }        for(month=1;month<=12;month++){            switch (month){                case 1:                case 3:                case 5:                case 7:                case 8:                case 10:                case 12:                    for(day=1;day<=31;day++){                        if(hy==month*100+day)                            printf("%d %d %d\n",year,month,day);                    }                    break;                case 4:                case 6:                case 9:                case 11:                    for(day=1;day<=30;day++){                        if(hy==month*100+day)                            printf("%d %d %d\n",year,month,day);                    }                    break;                case 2:                    if(year%4==0&&year%100!=0||year%400==0){                        for(day=1;day<=29;day++){                        if(hy==month*100+day)                            printf("%d %d %d\n",year,month,day);                        }                    }                    else                        for(day=1;day<=28;day++){                        if(hy==month*100+day)                            printf("%d %d %d\n",year,month,day);                        }            }        }    }    return 0;}

运行结果:



知识点总结:
     1.求完数(即找出一个数除它本身外的所有因数)        
        取余
     
     2.亲密数(本质上也是求因子和)
       取余

     3.分离出百、十、个位数 (利用求阿姆斯特朗数的方法联想到另一种更普遍的解法)  
  • c=n%10;  
  • b=(n/10)%10;  
  • a=n/100;  

     4.反序数(使末位数向左移一位并加上余数) 
  • k=n;  
  • m=0;  
  • while(k!=0){  
  •      m=m*10+k%10;    //m进一位并加上余数  
  •      k/=10;  
  •  }  

     5.回文数(一个数的反序数等于它本身)

     6.阿姆数斯特朗数(分离出每一位数)  
  • while(k!=0){ 
  •      m=k%10;  
  •       k/=10;
  • }     
 
     7.回文日(根据反序数的原理,并将年月日分成四部分,判断倒序后的日期是否与原日期一致)
        经过观察,如果年份的反序数就是月日的话,则ymd就是一个回文日,经分析,逻辑正确。不仅代码少了,从逻辑上,还减少了一半的运行量。



心得:

        随着学习的深化,一个新的解题思路,或者使程序结构更清晰,都能对现有程序进行改进。

       比如,在求回文日的时候, 我是利用 年份的反序数?=月份×100+日子,而贺利坚老师利用 月份?=年份后两位的反余数&&日子?=年份后两位的反余数,并把month,day提前表示出来,而不是放在判断表达式中,避免一个个试数,多次循环,利用is_cycle的判断表达式进行结果的输出,更具模块化。

      

阅读全文
1 0
原创粉丝点击