Problem
题意陈述
输入两个数N,C,若1~N之间有偶数个素数,则输出最中间的2C个素数,若有奇数个素数则输出最中间2C-1个素数,当要输出的素数列表大于1到N之间的素数个数则输出1-N之间的所有素数。
解题思路
解决该题有两个关键点: 1.查找1~N之间的素数列表;2.如何找到素数列表最中间的2C/2C-1个元素并输出
针对关键点1,由于N的值是有限制的(1~1000),所以为了提高效率可以先将1-N之间的所有素数找出来并存储到一个数组中去,后面只需要根据输入的N在该数组中从后往前即可找到在1-N范围内的素数列表。
针对关键点2,由于素数是存储在数组中的,当从后往前找到第一个不大于N的树时,根据其下标值推出1~N中素数列表中的素数个数,当素数列表的元素个数为奇数且2C-1不大于素数列表元素个数时,由数学可得最中间2C-1个元素的开始下标和结束下标为j/2-(C-1)和j/2+(C-1)(j为1-N素数序列中最大素数的下标),将其输出;当素数列表的元素个数为偶数且2C不大于素数列表元素个数时,可得其开始下标和结束下标为(j+1-2C)/2和(j+1-2C)/2+2C(j为1-N素数序列中最大素数的下标),将其输出;当由C得出的要输出的素数序列的值大于1-N中素数元素个数时,直接将1-N中的所有素数输出。
程序代码
#include <iostream>
#include <cmath>
using namespace std;
void FindPrime(int a[], int& k)//找到到1~1000中所有素数并存入数组中,k保存1~1000中最大素数的下标
{
int flag;
for (int i = 1; i <= 1000; i++)
{
flag = 1;
for (int j = 2; j <= sqrt(i); j++)
if (i % j == 0)
{
flag = 0;
break;
}
if (flag)
a[k++] = i;
}
}
int main()
{
int a[1001];
int k = 0;
int N, C;
FindPrime(a, k);
while (cin >> N >> C)
{
int j;
cout << N << " " << C << ":";
for (j = k - 1; j >= 0; j--)
if (a[j] <= N)
break;
if (2 * C > (j + 1) || (2 * C - 1) > (j + 1))//由C求出要输出的序列元素个数超过1~N中的素数个数
{
for (int m = 0; m <= j; m++)
cout << " " << a[m];
}
else
{
if ((j + 1) % 2 != 0)//1~N中有奇数个素数
{
int n = j / 2 + (C - 1);
for (int m = j / 2 - (C - 1); m <= n; m++)
cout << " " << a[m];
}
else//1~N中有奇数个素数
{
int n = ((j + 1) - 2 * C) / 2;
for (int m = n; m < n + 2 * C; m++)
cout << " " << a[m];
}
}
cout << endl << endl;
}
return 0;
}