Given an array of integers , we say a set is a prime set of the given array, if and is prime.
BaoBao has just found an array of integers in his pocket. He would like to select at most prime set of that array to maximize the size of the union of the selected sets. That is to say, to maximize by carefully selecting and , where and is a prime set of the given array. Please help BaoBao calculate the maximum size of the union set.
Input
There are multiple test cases. The first line of the input is an integer , indicating the number of test cases. For each test case:
The first line contains two integers and (, ), their meanings are described above.
The second line contains integers (), indicating the given array.
It's guaranteed that the sum of over all test cases will not exceed .
Output
For each test case output one line containing one integer, indicating the maximum size of the union of at most prime set of the given array.
Sample Input
4 4 2 2 3 4 5 5 3 3 4 12 3 6 6 3 1 3 6 8 1 1 1 0 1
Sample Output
4 3 6 0
Hint
For the first sample test case, there are 3 prime sets: {1, 2}, {1, 4} and {2, 3}. As , we can select {1, 4} and {2, 3} to get the largest union set {1, 2, 3, 4} with a size of 4.
For the second sample test case, there are only 2 prime sets: {1, 2} and {2, 4}. As , we can select both of them to get the largest union set {1, 2, 4} with a size of 3.
For the third sample test case, there are 7 prime sets: {1, 3}, {1, 5}, {1, 6}, {2, 4}, {3, 5}, {3, 6} and {5, 6}. As , we can select {1, 3}, {2, 4} and {5, 6} to get the largest union set {1, 2, 3, 4, 5, 6} with a size of 6.
题意:
给你n个数,如果{i, j}满足i!=j && a[i]+a[j]是一个质数,那么称{i, j}是个Pset
之后再给你一个k,然你找出最多k个这样的Pset二元组,使得所有二元组中出现的元素尽可能多
例如样例:
5 3
3 4 12 3 6
满足条件的二元组只有(1, 2)和(2, 4),所以这两个都选上就好了,答案为3
一个质数是由一个偶数和奇数组成(除了2)所以我们暂且不匹配1 让尽可能多的奇数去匹配偶数(因为1自身也可以匹配)
然后就是处理贡献为2和贡献为1的问题了
#include <iostream>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;
const int N = 3e3+10;
typedef long long LL;
vector<int>p[N];
const int M = 3000000;
int prime[M], match[N], vis[N], a[N], val[N];
int num,cnt1,cnt2,root;
int dfs(int u)
{
for(int i=0;i<p[u].size();i++)
{
int v=p[u][i];
if(vis[v]) continue;
vis[v]=1;
if(match[v]==-1||dfs(match[v]))
{
match[v]=u,match[u]=v;
return 1;
}
}
return 0;
}
int main()
{
memset(prime,0,sizeof(prime));
prime[1]=1;
for(int i=2;i<M-10;i++)
{
if(prime[i])continue;
for(int j=2*i;j<M-10;j+=i) prime[j]=1;
}
int t;
scanf("%d", &t);
while(t--)
{
int n, k;
scanf("%d %d", &n, &k);
for(int i=0;i<=n;i++)p[i].clear();
int s1=0;
for(int i=1;i<=n;i++)
{
scanf("%d", &a[i]);
if(a[i]==1)s1++;
}
memset(val,0,sizeof(val));
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(!prime[a[i]+a[j]])
{
val[i]=1,val[j]=1;
if(a[i]%2&&a[j]!=1)p[i].push_back(j);
else if(a[i]!=1)p[j].push_back(i);
}
}
}
memset(match,-1,sizeof(match));
int ans=0;
for(int i=1;i<=n;i++)
{
if(a[i]!=1)
{
memset(vis,0,sizeof(vis));
ans+=dfs(i);
}
}
for(int i=1;i<=n;i++)
{
if(a[i]==1)
{
memset(vis,0,sizeof(vis));
ans+=dfs(i);
}
}
if(ans>=k)printf("%d\n",k*2);
else
{
k-=ans;
for(int i=1;i<=n;i++)
{
if(match[i]!=-1&&a[match[i]]==1)s1--;
}
if(k*2<=s1)printf("%d\n",(ans+k)*2);
else
{
ans*=2;
k-=s1/2,ans+=s1/2*2;
for(int i=1;i<=n;i++)
{
if(k==0)break;
if(a[i]!=1&&match[i]==-1)
{
ans+=val[i],k-=val[i];
}
else if(a[i]==1&&val[i]&&s1%2)
{
ans+=1,k-=1;
s1=0;
}
}
printf("%d\n",ans);
}
}
}
return 0;
}