Description

给你 \(n\) 个数,去掉尽量少的数使得剩下数的最大公约数比原来的大。无解输出 \(-1\)

Solution

首先将所有数除以最大公约数

\(M=\max a_i\),维护一个桶 \(b[]\),对每个 \(i\),在 \(b[a[i]]\)\(+1\)

枚举 \([1,M]\) 中的所有质数 \(p\),考虑让最大公约数乘以 \(p\),代价就是我们需要删去所有的 \(a_i\) 满足 \(p|a_i\),于是我们枚举所有 \(p\) 的整数倍 \(q\),统计所有 \(b[q]\) 的和,就是 \(p\) 的答案

最后对所有 \(p\) 的答案取最小值即可

复杂度是 \(\sum_{p \leq M} M/i\),由于收敛较快,可以接受

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 16000005;
int prime[MAXN+1];

void presolve() {
    memset(prime,0,sizeof prime);
    for(int i=2;i<=MAXN;i++) {
        if(!prime[i]) prime[++prime[0]]=i;
        for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++) {
            prime[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
}

const int N = 1000005;
int n,a[N],b[MAXN];

signed main() {
    ios::sync_with_stdio(false);
    presolve();
    cin>>n;
    int g=0;
    for(int i=1;i<=n;i++) cin>>a[i], g=__gcd(g,a[i]);
    for(int i=1;i<=n;i++) a[i]/=g;
    for(int i=1;i<=n;i++) b[a[i]]++;
    int M = *max_element(a+1,a+n+1);
    int ans = 2e9;
    for(int i=1;prime[i]<=M;i++) {
        int p=prime[i];
        int sum=0;
        for(register int q=p;q<=M;q+=p) {
            sum+=b[q];
        }
        ans=min(ans,n-sum);
    }
    cout<<(ans>1e9?-1:ans)<<endl;
}

相关文章:

  • 2022-12-23
  • 2021-11-10
  • 2022-12-23
  • 2022-12-23
  • 2021-12-31
  • 2021-06-15
  • 2019-08-13
  • 2021-08-02
猜你喜欢
  • 2022-12-23
  • 2021-08-04
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-07-18
  • 2022-12-23
相关资源
相似解决方案