模拟赛今天似乎又考的很渣 要是像尹爷爷分一样高的话估计我THU稳了
这个题目很巧妙 利用差分完成区间修改
差分后我们的目标就是消去数组中所有的1
如果两个点距离差为奇质数 那么一次消掉即可
如果为偶数 根据哥德巴赫猜想才题目范围内是成立的 两次就可以消掉
不然三次也可以消掉
对于一次能消的进行二分图匹配 剩下的直接算就好了
注意事项:二分图匹配数组开大点, 连边的时候分清i, j
题目链接
#include<bits/stdc++.h>
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define SZ(x) int(x.size())
using namespace std;
const int maxn = 100 + 4, maxm = 1e7 + 10;
int P[maxn], C[maxn], n, vis[maxm];
int notprim[maxm], S[maxm];
vector<int> num, prime;
void Get_prime(int m)
{
notprim[0] = notprim[1] = 1;
For(i, 2, m)
{
if(!notprim[i])
prime.push_back(i);
int len = prime.size();
For(j, 0, len - 1)
{
if(prime[j] * i > m)
break;
notprim[prime[j] * i] = 1;
if(i % prime[j] == 0)
break;
}
}
}
namespace Match
{
const int N = 1e7 + 10;
int to[N], head[N], nxt[N], e;
int pre[N], vis[N], G[N], O[N], now, sum;
void add(int x, int y)
{
to[++ e] = y;
nxt[e] = head[x];
head[x] = e;
}
bool dfs(int x)
{
go(x, i)
{
if(vis[to[i]] != now)
{
vis[to[i]] = now;
if(!pre[to[i]] || dfs(pre[to[i]]))
{
pre[to[i]] = x;
return 1;
}
}
}
return 0;
}
int match()
{
int res = 0;
for(now = 1; now <= G[0]; ++ now)
res += dfs(now);
return res;
}
void solve()
{
int res = 0;
For(i, 0, SZ(num) - 1)
if(num[i] & 1)
G[++ G[0]] = num[i];
else
O[++ O[0]] = num[i];
For(i, 1, G[0])
For(j, 1, O[0])
if(!notprim[abs(G[i] - O[j])])
add(i, j);
res += match();
memset(vis, 0, sizeof(vis));
G[0] -= res, O[0] -= res;
res += G[0] / 2 * 2, G[0] %= 2;
res += O[0] / 2 * 2, O[0] %= 2;
if(G[0] * O[0])
res += 3;
cout << res << endl;
}
}
int main()
{
freopen("magic.in", "r", stdin);
freopen("magic.out", "w", stdout);
Get_prime(1e7 + 5);
scanf("%d", &n);
For(i, 1, n)
scanf("%d", &P[i]), vis[P[i]] ^= 1;
For(i, 1, maxm - 1)
if(vis[i] != vis[i - 1])
num.push_back(i);
memset(vis, 0, sizeof(vis));
Match::solve();
return 0;
}