CF1148G

まず、答えに影響を与えずに、すべてのデジタル素因数インデックスを1に設定します。
 
元の画像Gの補数を考慮して、与えられたn個の数値のf [i]がiの倍数であることをf [i]に示します。したがって、各ポイントについて、許容度と除外の原則を使用して次数を計算できます(つまり、元の配列のgcd = 1の数。たとえば、ポイント1の重みは6で、次にdeg [1] = n- (f [2] + f [3] -f [6])。
 
点Fが見つかれば、deg [F]> 1にして、エッジのない2つの点をGとHとします。上記3点を削除した後、2つのケースで議論します。
 
A:次数> 0のk-3ポイントが少なくともあり、最小のmは二分法によって検出されるため、最初のmポイントで構成されるグラフでは、次数> 0のk-3ポイントがまだあります。ディスカッションを強力に分類し、mポイントのエッジのみを持つ部分を削除し、必要に応じてF、G、Hを回答に追加します(詳細はコードを参照してください)。
 
B:2k <= nであるため、次数> 0のk-3ポイントはありません。少なくとも次数0のkポイントがあり、任意のkポイントを選択できます(重みは2または2 gcd> 1)。
 
点Fが見つからない場合、図の接続されたブロックのサイズは3未満であり、接続された各ブロックの点を選択して回答に追加できます。
 
代码:
`` `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;
}
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] ++;
  戻る;
 }
 add(i、pos + 1、S);
 add(i、pos + 1、S * arr [i] .fac [pos]);
 戻る;
}
void del(int i、int pos、int S)
{
 if(pos == arr [i] .cnt){
  if(S!= 1)f [S]-;
  戻る;
 }
 del(i、pos + 1、S);
 del(i、pos + 1、S * arr [i] .fac [pos]);
 戻る;
}
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)ad​​d(i、0,1);
 }
 n = 2 * k;
 戻る;
}
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];
 戻り値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 ++;
  他のi ++;
 }
 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);
  それ以外の場合m0--;
 int x = 0;
 for(int i = 0; i <= m; i ++){
  if(i == F || i == G || i == H)
   続行;
  deg [i] = m0-getdeg(i、0,1、-1);
  if(deg [i]> 0)
   x ++;
 }
 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;
  それ以外の場合、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 && deg [i] == 1 &&!common(i、m)){
    p--; deg [i] =-1;
   }
 }
 else {
  for(int i = 0; i <m && p> k-2;

    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 && deg [i]> 0)
   printf( "%d"、i + 1);
 戻る;
}
int main(void)
{
 getprime();
 読んだ();
 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 && deg [i] <= n-2)
   getFGH(i);
 }
 if(F ==-1){
  solve1();
  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();
 0を返します。
}
`` `

おすすめ

転載: www.cnblogs.com/2005lz/p/12690612.html