首先把所有数质因数指数设为1,不影响答案。
考虑原图G的补图,设f[i]表示给定n个数中有f[i]个数是i的倍数。于是对于每个点,我们可以用容斥原理计算它的度数(即原数组中与它gcd=1的数的个数。比如1号点权值为6,则有deg[1]=n-(f[2]+f[3]-f[6])。
如果可以找到点F,使deg[F]>1,设与其没有边相连的两个点为G,H。把以上三个点删除后分两种情况讨论。
A:有至少k-3个点的度数>0,二分找到最小的m,使在前m个点中构成的图中,仍然有k-3个点度数>0。大力分类讨论,删除部分仅与m号点有边的点,如果需要的话把F,G,H加入答案中即可(具体见代码)。
B:度数>0的点没有k-3个,因为2k<=n,所以至少有k个点度数为0,选取其中任意k个点即可(其权值两两gcd>1)。
如果找不到点F,则图中连通块的大小均小于3,在每个连通块中选取一个点加入答案中即可。
代码:
```cpp
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
```cpp
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k,t;
int pcnt=0,pri[100000];
bool isp[1000000];
void getprime(void)
{
memset(isp,1,sizeof(isp));
for(int i=2;i<1000000;i++)
if(isp[i]){
pri[pcnt++]=i;
for(int j=2;i*j<1000000;j++)
isp[i*j]=0;
}
return;
}
int pcnt=0,pri[100000];
bool isp[1000000];
void getprime(void)
{
memset(isp,1,sizeof(isp));
for(int i=2;i<1000000;i++)
if(isp[i]){
pri[pcnt++]=i;
for(int j=2;i*j<1000000;j++)
isp[i*j]=0;
}
return;
}
struct num{
int fac[10],cnt;
}arr[100000];
int f[10000000];
void add(int i,int pos,int S)
{
if(pos==arr[i].cnt){
if(S!=1) f[S]++;
return;
}
add(i,pos+1,S);
add(i,pos+1,S*arr[i].fac[pos]);
return;
}
void del(int i,int pos,int S)
{
if(pos==arr[i].cnt){
if(S!=1) f[S]--;
return;
}
del(i,pos+1,S);
del(i,pos+1,S*arr[i].fac[pos]);
return;
}
void read(void)
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%d",&t);
arr[i].cnt=0;
for(int j=0;pri[j]*pri[j]<=t;j++)
if(t%pri[j]==0){
arr[i].fac[arr[i].cnt++]=pri[j];
while(t%pri[j]==0)
t/=pri[j];
}
if(t>1) arr[i].fac[arr[i].cnt++]=t;
if(i<2*k) add(i,0,1);
}
n=2*k;
return;
}
int fac[10],cnt;
}arr[100000];
int f[10000000];
void add(int i,int pos,int S)
{
if(pos==arr[i].cnt){
if(S!=1) f[S]++;
return;
}
add(i,pos+1,S);
add(i,pos+1,S*arr[i].fac[pos]);
return;
}
void del(int i,int pos,int S)
{
if(pos==arr[i].cnt){
if(S!=1) f[S]--;
return;
}
del(i,pos+1,S);
del(i,pos+1,S*arr[i].fac[pos]);
return;
}
void read(void)
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%d",&t);
arr[i].cnt=0;
for(int j=0;pri[j]*pri[j]<=t;j++)
if(t%pri[j]==0){
arr[i].fac[arr[i].cnt++]=pri[j];
while(t%pri[j]==0)
t/=pri[j];
}
if(t>1) arr[i].fac[arr[i].cnt++]=t;
if(i<2*k) add(i,0,1);
}
n=2*k;
return;
}
int deg[100000],F=-1,G=-1,H=-1;
int getdeg(int i,int pos,int S,int opt)
{
if(pos==arr[i].cnt)
return opt*f[S];
return getdeg(i,pos+1,S,opt)+getdeg(i,pos+1,S*arr[i].fac[pos],-opt);
}
inline bool common(int a,int b)
{
int i=0,j=0;
while(i<arr[a].cnt&&j<arr[b].cnt){
if(arr[a].fac[i]==arr[b].fac[j])
return 1;
if(arr[a].fac[i]>arr[b].fac[j])
j++;
else i++;
}
return 0;
}
void getFGH(int i)
{
F=i;
for(int j=0;j<n;j++)
if(!common(i,j)){
if(G==-1) G=j;
else if(H==-1) H=j;
}
return;
}
int getdeg(int i,int pos,int S,int opt)
{
if(pos==arr[i].cnt)
return opt*f[S];
return getdeg(i,pos+1,S,opt)+getdeg(i,pos+1,S*arr[i].fac[pos],-opt);
}
inline bool common(int a,int b)
{
int i=0,j=0;
while(i<arr[a].cnt&&j<arr[b].cnt){
if(arr[a].fac[i]==arr[b].fac[j])
return 1;
if(arr[a].fac[i]>arr[b].fac[j])
j++;
else i++;
}
return 0;
}
void getFGH(int i)
{
F=i;
for(int j=0;j<n;j++)
if(!common(i,j)){
if(G==-1) G=j;
else if(H==-1) H=j;
}
return;
}
void solve1(void)
{
for(int i=0;i<n;i++)
del(i,0,1);
int cnt=0;
for(int i=0;i<n&&cnt<k;i++)
if(getdeg(i,0,1,-1)==cnt){
cnt++;
printf("%d ",i+1);
add(i,0,1);
}
return;
}
int check(int m)
{
int m0=m+1;
for(int i=0;i<=m;i++)
if(i!=F&&i!=G&&i!=H)
add(i,0,1);
else m0--;
int x=0;
for(int i=0;i<=m;i++){
if(i==F||i==G||i==H)
continue;
deg[i]=m0-getdeg(i,0,1,-1);
if(deg[i]>0)
x++;
}
return x;
}
{
for(int i=0;i<n;i++)
del(i,0,1);
int cnt=0;
for(int i=0;i<n&&cnt<k;i++)
if(getdeg(i,0,1,-1)==cnt){
cnt++;
printf("%d ",i+1);
add(i,0,1);
}
return;
}
int check(int m)
{
int m0=m+1;
for(int i=0;i<=m;i++)
if(i!=F&&i!=G&&i!=H)
add(i,0,1);
else m0--;
int x=0;
for(int i=0;i<=m;i++){
if(i==F||i==G||i==H)
continue;
deg[i]=m0-getdeg(i,0,1,-1);
if(deg[i]>0)
x++;
}
return x;
}
void solve2(void)
{
for(int i=0;i<n;i++)
if(i!=F&&i!=G&&i!=H)
del(i,0,1);
int l=k-4,r=n-2,m;
while(l<r){
m=(l+r+1)>>1;
if(check(m)>=k-3)
r=m-1;
else l=m;
for(int i=0;i<=m;i++)
if(i!=F&&i!=G&&i!=H)
del(i,0,1);
}
m=l+1;
int p=check(m);
if(p>=k){
for(int i=0;i<m&&p>k;i++)
if(i!=F&&i!=G&&i!=H&°[i]==1&&!common(i,m)){
p--; deg[i]=-1;
}
}
else{
for(int i=0;i<m&&p>k-2;i++)
if(i!=F&&i!=G&&i!=H&°[i]==1&&!common(i,m)){
p--; deg[i]=-1;
}
printf("%d %d ",F+1,G+1);
if(p==k-3)
printf("%d ",H+1);
}
for(int i=0;i<=m;i++)
if(i!=F&&i!=G&&i!=H&°[i]>0)
printf("%d ",i+1);
return;
}
{
for(int i=0;i<n;i++)
if(i!=F&&i!=G&&i!=H)
del(i,0,1);
int l=k-4,r=n-2,m;
while(l<r){
m=(l+r+1)>>1;
if(check(m)>=k-3)
r=m-1;
else l=m;
for(int i=0;i<=m;i++)
if(i!=F&&i!=G&&i!=H)
del(i,0,1);
}
m=l+1;
int p=check(m);
if(p>=k){
for(int i=0;i<m&&p>k;i++)
if(i!=F&&i!=G&&i!=H&°[i]==1&&!common(i,m)){
p--; deg[i]=-1;
}
}
else{
for(int i=0;i<m&&p>k-2;i++)
if(i!=F&&i!=G&&i!=H&°[i]==1&&!common(i,m)){
p--; deg[i]=-1;
}
printf("%d %d ",F+1,G+1);
if(p==k-3)
printf("%d ",H+1);
}
for(int i=0;i<=m;i++)
if(i!=F&&i!=G&&i!=H&°[i]>0)
printf("%d ",i+1);
return;
}
int main(void)
{
getprime();
read();
int w=0;
for(int i=0;i<n;i++){
deg[i]=getdeg(i,0,1,-1);
if(deg[i]<n) w++;
if(F==-1&°[i]<=n-2)
getFGH(i);
}
if(F==-1){
solve1();
return 0;
}
for(int i=0;i<n;i++)
del(i,0,1);
if(check(n-1)<k-3){
for(int i=0;i<n&&k>0;i++)
if(deg[i]==0){
printf("%d ",i+1);
k--;
}
}
else solve2();
return 0;
}
```
{
getprime();
read();
int w=0;
for(int i=0;i<n;i++){
deg[i]=getdeg(i,0,1,-1);
if(deg[i]<n) w++;
if(F==-1&°[i]<=n-2)
getFGH(i);
}
if(F==-1){
solve1();
return 0;
}
for(int i=0;i<n;i++)
del(i,0,1);
if(check(n-1)<k-3){
for(int i=0;i<n&&k>0;i++)
if(deg[i]==0){
printf("%d ",i+1);
k--;
}
}
else solve2();
return 0;
}
```