题目:
程序接收用户输入的一个数N,输出从1到N(包括N)的所有合数之和。输入一个整数N(0<N<=1000),输出从1到N中所有合数的和。
思路:
定义一个数组存放1~N之间的自然数,然后对每个自然数进行判断,若不为合数,就将此数置0,最后对该数组求和,即得解。
代码如下:
#include "stdafx.h"
#include<iostream>
using namespace std;
int main()
{
int N; //用户输入的数
int i,j;
cout << "输入N:";
cin >> N;
//找到1~N之间的合数
int *num = new int[N+1]; //存放1~N中的合数
//初始化num数组,先将所有自然数都放入其中,后面进行筛除(赋值为0)
for(i=0;i<=N;i++)
num[i] = i;
//先将特殊的两个数赋为0
num[1] = 0; //1既不是合数也不是质数
num[2] = 0; //2为质数
int isPrime = 1; //标志变量,isPrime为0表示为合数,为1表示为质数
//对3~N之间的数进行合数判断
for(i=3;i<=N;i++)
{
//判断是否为质数,若为质数,则将其置0
for(j=2;j*j<=i;j++)
{
if(i%j == 0)
{
isPrime = 0; //该数为合数
break;
}
}
//若为质数,则将此数删除(赋值为1)
if(isPrime == 1)
num[i] = 0;
isPrime = 1;
}
int sum = 0;
for(i=1;i<=N;i++)
sum = sum + num[i];
cout << "1到" << N << "(包括N)的所有合数之和为:" << sum << endl;
system("pause");
return 0;
}
运行结果如下:
书上提供了另外一种思路,因为0<N<=1000,因此先将0~1000之间的数预先进行判断。设置大小为1000的数组,用于存储1~1000所有的数,对数组中合数的下标进行标记。从3到输入的数N进行合数的枚举累加。
代码如下:
#include "stdafx.h"
#include<iostream>
using namespace std;
bool prim[1000]; //存放1~1000之间数的判断结果(合数为true,其它数为false)
void init()
{
//采用筛除法,从2开始,挑出后面是其倍数的数(置为ture)
for(int i=2;i<=1000;i++)
{
if(!prim[i])
{
for(int j=2;j*i<=1000;j++)
prim[j*i] = true;
}
}
}
int main()
{
init();
int n;
cin >> n;
int sum = 0;
//求和
for(int k=3;k<=n;k++)
{
//略过不是合数的数
if(prim[k])
sum += k;
}
cout << sum << endl;
system("pause");
return 0;
}
值得学习的是其判断合数的方法(判断质数中叫筛除法),比一般的方法节约运行时间。
书上是先将1~1000的合数进行预处理,预处理的时候花的时间较多,后续求和就比较快了。因此如果用户需要输入很多个N,则预处理这种方法比较实际。
运行结果如下: