所有题解基本都有的问题就是认为只有奇数+偶数才能是素数,忽略了1+1和0+2(本题只存在1+1的情况)的情况。 所以类似
4
1 1 2 3
2
1 1
这样的两组数据都会忽略1+1的配对。 所以考虑对奇数从大到小排序,优先配对比1大的奇数,没得配了再用1和偶数配对,最后统计没配对的1的数量,再让其互相两两配对。(不确定是否还有漏洞,但是可以过类似上面的数据了)
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int N = 110, M = 2510;
int n;
int h[N], e[M], ne[M], idx;
int match[N];//match[i]表示第i个偶数匹配的是第match[i]个奇数
vector<int> even, odd;
bool st[N], f[N];//f[i]表示第i个奇数是否有匹配的偶数
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
bool isprime(int n)
{
for (int i = 2; i * i <= n; i ++)
if (n % i == 0)
return false;
return true;
}
bool find(int x)
{
for (int i = h[x]; ~i; i = ne[i])
{
int j = e[i];
if (!st[j])
{
st[j] = true;
if (match[j] == -1 || find(match[j]))
{
match[j] = x;
return true;
}
}
}
return false;
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++)
{
int x; cin >> x;
if (x & 1) odd.push_back(x);
else even.push_back(x);
}
// if (!odd.size() || !even.size())
// {
// puts("0");
// return 0;
// }
int cnt = 0;
memset(h, -1, sizeof h);
memset(match, -1, sizeof match);
sort(odd.begin(), odd.end(), greater<int>());//尽量最后再匹配1
for (int i = 0; i < odd.size(); i ++)
for (int j = 0; j < even.size(); j ++)
if (isprime(odd[i] + even[j]))
add(i, j);
for (int i = 0; i < odd.size(); i ++)
{
memset(st, 0, sizeof st);
if (find(i))
{
cnt ++;
f[i] = true;
}
}
int k = 0;
for (int i = 0; i < odd.size(); i ++)//寻找没匹配过的1
if (odd[i] == 1 && !f[i])
k ++;
cnt += k / 2;
cout << cnt << endl;
return 0;
}