Problem - C - Codeforces
Mr. F 有 n 个正整数 a1,a2,…,an。
他认为这些整数的最大公约数太小了。所以他想通过删除其中一些整数来扩大它。
但是这个问题对他来说太简单了,所以他不想自己做。如果你帮他解决这个问题,他会给你一些奖励分数。
你的任务是计算您需要删除的最少数量的整数,以便剩余整数的最大公约数大于所有整数的最大公约数。
输入 第一行包含一个整数 n (2≤n≤3⋅105) — Mr. F 拥有的整数数量。
第二行包含 n 个整数 a1,a2,…,an (1≤ai≤1.5⋅107)。
输出 请输出一个整数 — 您需要删除的最少数量的整数,以便剩余整数的最大公约数大于所有整数的最大公约数。
您不应该删除所有整数。
如果没有解决方案,请输出 "-1"(不要引号)。
Examples
input
Copy
3 1 2 4
output
Copy
1
input
Copy
4 6 9 15 30
output
Copy
2
input
Copy
3 1 1 1
output
Copy
-1
在第一个例子中,最大公约数一开始为1。你可以去掉1,使得最大公约数变成2。答案是1。
在第二个例子中,最大公约数一开始为3。你可以去掉6和9,使得最大公约数变成15。没有只去掉一个整数就能实现的解决方案。因此答案是2。
在第三个例子中,没有办法扩大最大公约数。因此答案是-1。
题解:
对于有很多数据的题目尽量不用map,用数组进行操作,
一般来说,题目给的内存限制,只够我们开到2e7的数组
对于不是太大的输入输出,如果超时,可能时#define int long long的原因
对于本题来说,首先线性筛筛质数,
每个数/数组的最大公约数,记录剩下数中都含有什么因子,
含有的因子最多的便是我们应该保留的数目
注意特判,数组中数全部相等的情况
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//#define int long long
typedef pair<int,int> PII;
const int N = 1.5e7 + 10;
int mod = 1e9 + 7;
int pri[N/10];
int vis[N];
int a[300050];
int c[N];
void solve()
{
int n;
scanf("%d",&n);
int cnt = 0;
for(int i = 2;i <= N - 10;i ++)
{
if(!vis[i])
{
pri[++cnt] = i;
}
for(int j = 1;j <= cnt&&i*pri[j] <= N;j++)
{
vis[i*pri[j]] = 1;
if(i%pri[j] == 0)
break;
}
}
int g = 0;
for(int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
g = __gcd(a[i],g);
}
for(int i = 1;i <= n;i++)
{
a[i] /= g;
for(int j = 1;pri[j]*pri[j] <= a[i];j++)
{
if(a[i]%pri[j] == 0)
{
c[pri[j]]++;
while(a[i]%pri[j] == 0)
{
a[i] /= pri[j];
}
}
}
if(a[i] > 1)
c[a[i]]++;
}
int ans = 1e9;
for(int i = 1;i <= N - 10;i++)
{
ans = min(ans,n - c[i]);
}
if(ans == n)
{
printf("-1");
}
else
{
printf("%d",ans);
}
}
signed main()
{
// ios::sync_with_stdio(0 );
// cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}