問題描述
求某一范圍內(nèi)完數(shù)的個(gè)數(shù)。
如果一個(gè)數(shù)等于它的因子之和,則稱該數(shù)為“完數(shù)”(或“完全數(shù)”)。例如,6的因子為1、2、3,而 6=1+2+3,因此6是“完數(shù)”。
問題分析
根據(jù)完數(shù)的定義,解決本題的關(guān)鍵是計(jì)算出所選取的整數(shù)i(i的取值范圍不固定)的因子(因子就是所有可以整除這個(gè)數(shù)的數(shù)),將各因子累加到變量s (記錄所有因子之和),若s等于i,則可確認(rèn)i為完數(shù),反之則不是完數(shù)。
算法設(shè)計(jì)
對(duì)于這類求某一范圍(由于本題范圍不固定,在編程過程中采用鍵盤輸入的方式)內(nèi)滿足條件的數(shù)時(shí),一般釆用遍歷的方式,對(duì)給定范圍內(nèi)的數(shù)值一個(gè)一個(gè)地去判斷是否滿足條件,這一過程可利用循環(huán)來實(shí)現(xiàn)。
本題的關(guān)鍵是求出選取數(shù)值i的因子,即從1到i-1范圍內(nèi)能整除i的數(shù),看某一個(gè)數(shù)j是否為i的因子,可利用語句if(i%j==0)進(jìn)行判斷,求某一個(gè)數(shù)的所有因子,需要在1到i-1范圍內(nèi)進(jìn)行遍歷,同樣釆用循環(huán)實(shí)現(xiàn)。因此,本題從整體上看可利用兩層循環(huán)來實(shí)現(xiàn)。外層循環(huán)控制該數(shù)的范圍2〜n;內(nèi)層循環(huán)j控制除數(shù)的范圍為1〜i,通過i對(duì)j取余,是否等于0,找到該數(shù)的各個(gè)因子。
另外應(yīng)注意每次判斷下一個(gè)選定數(shù)之前,必須將變量s的值重新置為0,編程過程中一定要注意變量s重新置0的位置。
程序流程圖:
下面是完整的代碼:
#include<stdio.h>
int main()
{
int i, j, s, n; /*變量i控制選定數(shù)范圍,j控制除數(shù)范圍,s記錄累加因子之和*/
printf("請(qǐng)輸入所選范圍上限:");
scanf("%d", &n); /* n的值由鍵盤輸入*/
for( i=2; i<=n; i++ )
{
s=0; /*保證每次循環(huán)時(shí)s的初值為0*/
for( j=1; j<i; j++ )
{
if(i%j == 0) /*判斷j是否為i的因子*/
s += j;
}
if(s == i) /*判斷因子這和是否和原數(shù)相等*/
printf("It's a perfect number:%d\n", i);
}
return 0;
}
運(yùn)行結(jié)果:
請(qǐng)輸入所選范圍上限:10000↙︎
It's a perfect number:6
It's a perfect number:28
It's a perfect number:496
It's a perfect number:8128
知識(shí)點(diǎn)補(bǔ)充
上述程序中求某數(shù)的因子時(shí),釆用從1到i-1范圍內(nèi)進(jìn)行遍歷的方法,一個(gè)數(shù)一個(gè)數(shù)地去試。這種方法可以做到?jīng)]有遺漏,但是效率不高。
對(duì)于某一整數(shù)來說,其最大因子為n/2 (若n為偶數(shù)時(shí),若為奇數(shù)最大因子小于n/2),在n/2〜n-1范圍內(nèi)沒有數(shù)據(jù)可以整除此數(shù)。據(jù)此,我們可以把遍歷范圍縮小至1〜n-1,這樣程序效率可以提高一倍。相應(yīng)程序如下:
#include<stdio.h>>
int main()
{
//...
for( i=2; i<=1000; i++)
{
s=0;
for( j=1; j<=n/2; j++ )
{
if(i%j == 0)
s += j;
}
//...
}
}</stdio.h>