XD-OJ T30
标题: 完数
类别: 时间限制: 2 S
内存限制: 10000 Kb
问题描述: 请写一个程序,给出指定整数范围[a,b]内的所有完数,0 < a < b < 10000。
一个数如果恰好等于除它本身外的所有因子之和,这个数就称为”完数”。
例如6是完数,因为6=1+2+3 输入说明 输入为两个整数a和b,a和b之间用空格分隔
输出说明 输出[a,b]内的所有完数,每个数字占一行
输入样例 1 10
输出样例 6
简单的思路:
在[a,b]中取得一个数,求这个数字的所有因数,相加,之后与原数字比较,如果相等,原数字即为完数。
遍历[a,b]的所有数字,重复以上操作。
起初的想法是用数组来做,把每个因数保存到数组c[n]当中,然后对c[n]求和,再将完数储存到另一个数组当中,最后遍历输出另一个数组d[n]
第一次提交的代码
#include <stdio.h>
int main() {
int a, b, c[10000], d[10000], i, n, g, k, l, sum;
n = 1;
k = 1;
sum = 0;
scanf("%d %d", &a, &b);
c[0] = 0;
while (1) { //对一个数b求因数,将每个因数放到数组里
for (i = 1; i <= b - 1; i++)
if (b % i == 0) {
c[n] = i;
n++;
};
for (g = 1; g <= n; g++) {
sum = sum + c[g];
}
//判断b是否是完数,如果是,把这个值赋给数组dn中的一项
if (sum == b) {
d[k] = sum;
k++;
}
sum = 0;
b = b - 1;
if (b <= a)
break;
}
for (l = 1; l < k; l++) {
printf("%d", d[l]);
}
return 0;
}
然而并没有预期的输出,这是为什么呢怎么会事呢
删除循环结构,发现这种思路判断一个数字是可行的,套上循环就错误。
具体而言是无输出结果,或者运行时错误。百思不得其解的我询问了某个大佬学长。
他给出的建议是
Robotxm
每次循环的时候sum置零,甚至你可以删掉数组c,计算因数的循环里直接给sum加
我好像想到了什么。
快看14行和16行,这里有两个计数的变量,还有一个sum变量。
先按照学长的建议,在程序循环内的最后一行加上
sum=0;
但是事情远没有这么简单
在进行下一次循环时,初始化sum=0确实没错,但是这个时候的n,是从上次循环接续下来的,比如说上一次循环有7个因数,那么结束循环时n=8,再赋值,假设有10个因数那就是从c[8]赋到从c[17]
再次求和时,g是从1开始的,也就是说,是从c[1]一直加到c[18],为什么是c[18]呢?
接着上边的例子,原因是求因数的循环结束之后,n++使得n=18,那也就相当于从n=1一直求和到n=18,求和的数字不仅仅是对这个数字的因数,还包括上个数字的因数。
好了,明白了症结,那我们开始改。
首先为了计数时存放因数的数组总是便于求和,我们数组编号总是从1开始,每次存放因数的数组总是从c[1]到c[n]。
其次,在求和时,我们要加所有的因数,不能多加,也不能少加,在上边的求因数结束以后,n++,即n比因数的个数要多1。所以我们求和时,求到
q=n-1
即可。
改好了贴成品
#include <stdio.h>
int main() {
int a, b,c[10000],d[10000], i, n, g, k, l, sum;
n = 1;
k = 1;
sum = 0;
c[0]=0;
scanf("%d %d",&a,&b);
for(;b>=a;b--) { //对一个数b求因数,将每个因数放到数组里
for (i = 1; i <= b-1 ; i++) {
if (b % i == 0) {
c[n] = i;
n++;
}
}
for (g = 1; g <n; g++) {
sum = sum + c[g];
}
//判断b是否是完数,如果是,把这个值赋给数组dn中的一项
if (sum == b) {
d[k] = sum;
k++;
}
sum = 0;
g=1;
n=1;
}
for (l = 1; l < k; l++) {
printf("%d\n", d[l]);
}
return 0;
}
还有第二种去掉了c[n]的版本
#include<stdio.h>
int main()
{
int i, j, s, a,b; /*变量i控制选定数范围,j控制除数范围,s记录累加因子之和*/
scanf("%d %d", &a,&b); /* n的值由键盘输入*/
for( i=a; i<=b; i++ )
{
s=0; /*保证每次循环时s的初值为0*/
for( j=1; j<i; j++ )
{
if(i%j == 0) /*判断j是否为i的因子*/
s += j;
}
if(s == i) /*判断因子这和是否和原数相等*/
printf("%d\n", i);
}
return 0;
}
嗯,每次循环之后变量归位。
你是不是想到了函数的调用?(形参)
或许还能有第三个版本。
To be continue;