【问题描述】
设n为一个正整数,100<=n<=10000,请找到素数x,x<=n,使得n-p*x最大,其中p是整数,使得p*x<=n<=(p+1)*x。
输入:
输入的第一行给出一个整数M,表示测试用例的个数。每个测试用例一行,给一个整数N,100<=N<=10000。
输出:
对输入的每个测试用例输出一行,给出满足上述条件的素数。
样例输入 | 样例输出 |
5 4399 614 8201 101 7048 | 2203 311 4111 53 3527 |
【解题思路】
要使得n-p*x最大,(x为素数,p为整数,p*x<=n<=(p+1)*x),则x为所有小于n的素数中,被n除后余数最大的一个素数。由此可得出算法:先离线计算出[2...10000]的素数表SU[],表长为num,然后每输入一个整数n,则枚举小于n的所有素数,计算tmp=max{n%SU[i]|SU[i]<n}其中1<=i<=num,满足条件的素数即为对应tmp=n%SU[k]的素数SU[k]。
【具体实现】
#include<iostream>
#include<cmath>
/*n的上下限*/
#define maxNum 10000
#define minNum 100
using namespace std;
/*素数筛*/
int SIGN[maxNum];
/*保存所有素数*/
int SU[maxNum];
int main(){
/*离线计算出素数筛*/
SIGN[0] = SIGN[1] = 1;
for (int i = 2; i <= maxNum; ++i){
for (int j = 2; j <= sqrt(i); ++j)
if (i%j == 0)
SIGN[i] = 1;
}
/*将素数筛中的素数保存至SU[]*/
int num = 0;
for (int k = 0; k < maxNum;++k)
if (!SIGN[k])
SU[num++] = k;
int times;//输入次数
int N;//保存待处理值
while (cin >> times){
for (int b = 0; b < times; ++b){
cin >> N;
int k = 0;//保存余数最大时的项数值a
int tmp = 0;//保存余数最大值
for (int a = 0; a < num - 1; ++a)
if (SU[a] < N&&tmp < N%SU[a]){
tmp = N%SU[a];
k = a;
}
cout << SU[k] << endl;
}
}
return 0;
}
【额外补充】
原来wustoj上也有UVa的题啦。