codeforces 1034A-A. Enlarge GCD

原题链接

在这里插入图片描述

题目大意

给定n个正整数分别为 a 1 , a 2 . . . . . a n a_1,a_2.....a_n a1,a2.....an,问至少删掉多少个数可以使得当前数的最大公因数会大于最初n个正整数的最大公因数

思路分析

首先我们可以得到最初 n n n个数的 g c d gcd gcd d d d,然后将原数组全部除以 d d d,即对于所有的 1 ≤ i ≤ n 1 \leq i \leq n 1in,都有 s i = a i / d s_i=a_i/d si=ai/d
很明显,现在 g c d ( s 1 , s 2 . . . . s n ) = 1 gcd(s_1,s_2....s_n)=1 gcd(s1,s2....sn)=1,此时,我们只需要删掉几个数使得 g c d ( s 1 , s 2 , . . . . . s n ) > 1 gcd(s_1,s_2,.....s_n)>1 gcd(s1,s2,.....sn)>1即可。
此时,如果尝试直接求要删掉的最小数量有点困难(也可能是我菜,悲),但是我们可以反过来考虑,尝试求出剩下来的数的最大数量是可行的,我们只要尝试枚举 s i s_i si的约数,比如所有为2的倍数的个数,求出最大值然后再用 n n n减去便可。我们设 m a = m a x ( s 1 , s 2 . . . . s n ) ma=max(s_1,s_2....s_n) ma=max(s1,s2....sn),很明显约数的范围在 [ 1 , m a ] [1,ma] [1,ma]中。在这里我们可以用质数枚举一下,对于区间中不范围的数(除了1),它对应的值已经在枚举它的质因子的过程中,已经被用过了,所以可以直接用线性筛筛出 [ 1 , m a ] [1,ma] [1,ma]中的质数,然后用质数枚举即可,具体可参照代码

参考代码

void oula(int n)
{
   for(int i=2;i<=n;i++)
   {
    if(!vis[i])
    {
        prime[cnt++]=i;
    }
    
        for(int j=0;i*prime[j]<=n;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
   }
}
int num[N];
inline int gcd(int a,int b)
{
    if(b==0) return a;
    else return gcd(b,a%b);
}
void solve()
{
  int n;
  cin>>n;
  int d=0;
  for(int i=1;i<=n;i++) cin>>s[i],d=gcd(d,s[i]);
int ma=-1;
for(int i=1;i<=n;i++)
{
    s[i]=s[i]/d;
    num[s[i]]++;
    ma=max(s[i],ma);
}
oula(ma);
int ans=0;
//cout<<cnt<<endl;

for(int i=0;i<cnt;i++)
{
  int sum=0;
  for(int j=prime[i];j<=ma;j+=prime[i])
  {
    sum+=num[j];
  }
  if(sum>0)
  {
     ans=max(ans,sum);
  }
}
if(ans==0) cout<<-1<<endl;
else cout<<n-ans<<endl;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值