题目描述
有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);