题目描述
有n个小朋友一起结伴同行去上学,每个小朋友的口袋里都有一些糖果,孩子的世界总是单纯而又可爱,现在其中的小刷提出了一个问题,如果把某些人(大于等于1个人)的糖果组合起来,能否组合出素数个糖果呢?如果能够组合出素数个糖果,能组成的最大的素数又是多少呢?如果不能,又最接近于哪个素数呢?如果一样接近,最大的又是哪个素数呢?
看,小刷的世界就是这么单洁而又可爱!
输入
第一行输入一个n,紧接着下一行输入n个整数ai表示n个小朋友口袋里的糖果。
(n <= 100 ai <= 10000,ai之和<=10000)
输出
对于每组数据,输出一个数answer,表示能组合出来的最大的素数,如果不能组合出素数, 输出能组合出来的最接近的素数,如果有多个,输出最大的那个。即满足abs(answer - i)是最小的,且answer最大。( i是能通过若干个小朋友组合出来的糖果数量)输出的素数小于10000
样例输入
1
3
1
10
样例输出
3
11
提示
输出的素数小于10000
#include <bits/stdc++.h>
using namespace std;
int n;
int a[110];
int pri[2000];
bool dp[10010];
int can[10010];
bool prime (int x) //判定素数
{
for (int i = 2; i * i <= x; i++)
if (x % i == 0) return 0;
return 1;
}
int main()
{
int T = -1;
for (int i = 2; i <= 10000; i++)
{
if (prime(i))
{
T++;
pri[T] = i;
}
} //将素数从小到大存进pri数组中
while (~scanf ("%d", &n))
{
int total = 0;
for (int i = 0; i < n; i++)
{
scanf ("%d", &a[i]);
total += a[i];
}
memset (dp, 0, sizeof (dp));
dp[0] = 1;
int Q = -1;
for (int i = 0; i < n; i++)
{
for (int j = total; j >= a[i]; j--)
{
if (dp[j - a[i]] && dp[j] == 0)
//dp[j]==0 保证can中无重复
{
dp[j] = 1;
can[++Q] = j;
}
}
}
sort (can, can + Q + 1, less<int>() ); //从小到大
int minn = 1e9;
int ans = -1;
int t = lower_bound (pri, pri + T + 1, total) - pri;
for (int i = min (t, 1228); i >= 0; i --) //从大到小
{
int g = pri[i];
int p = lower_bound (can, can + Q + 1, g) - can;
//p = min (p, 1228); p在can上 无限制
int u;
if (p == 0) u = abs (g - can[p]);
else if(p == Q+1) u = abs(g - can[p-1]);
else u = min (abs (g - can[p]), abs (g - can[p - 1]) );
if (minn > u)
{
minn = u;
ans = g;
}
}
printf ("%d\n", ans);
}
return 0;
}
for (int i = 0; i < 10010; i++)
{
L[i] = 1e9;
R[i] = 1e9;
}
for (int i = 1; i <= 10000; i++)
{
if (dp[i]) //i可被组成
L[i] = i;
else
L[i] = L[i - 1];
}
for (int i = 10000; i >= 0; i--)
{
if (dp[i])
R[i] = i;
else
R[i] = R[i + 1];
}
int mminn = 1e9;
int res = -1;
for (int i = T; i >= 0; i--)
{
int q = pri[i];
int u = min (abs (q - L[q]), abs (q - R[q]) );
if (mminn > u)
{
mminn = u;
res = pri[i];
}
}
printf ("%d\n", res);