给定 N 个数字,任务是找到最小的移除数字,使得剩余数字的 GCD 大于 N 个数字的初始 GCD。如果不能增加 GCD,打印“NO”。
例子:
Input: a[] = {1, 2, 4}
Output: 1
Remove the first element, then the new GCD is 2, which is greater than the initial GCD i.e., 1.
Input: a[] = {6, 9, 15, 30}
Output: 2
The initial gcd is 3, remove 6 and 9 to obtain a gcd of 15 which is greater than 3. You can also remove 9 and 15 to get a gcd of 6.
按照以下步骤解决上述问题:
- 最初使用欧几里德算法找到 N 个数字的 gcd。
- 将所有数字除以得到的 gcd。
- 使用多查询的质因数分解方法,在 O(log N) 中找到每个数字的质数因数分解。该方法可以在这里阅读。
- 插入集合中的所有质因子以删除使用此方法获得的重复项。
- 使用哈希映射,计算每个第 i 个元素中素因子的频率。
- 一旦数字的因式分解完成,并且计数已存储在频率表中,则在哈希图中迭代并找出出现次数最多的素因数。它不能是 N,因为我们已经将数组元素最初除以 N 个数字的初始 gcd。
- 如果在初始 gcd 划分后存在任何此类因素,则移除次数将始终为 n-(hash[prime_factor])。
下面是上述方法的实现。
C++
// C++ program to find the minimum removals
// such that gcd of remaining numbers is more
// than the initial gcd of N numbers
#include
using namespace std;
#define MAXN 100001
// stores smallest prime factor for every number
int spf[MAXN];
// Calculating SPF (Smallest Prime Factor) for every
// number till MAXN.
// Time Complexity : O(nloglogn)
void sieve()
{
spf[1] = 1;
for (int i = 2; i < MAXN; i++)
// marking smallest prime factor for every
// number to be itself.
spf[i] = i;
// separately marking spf for every even
// number as 2
for (int i = 4; i < MAXN; i += 2)
spf[i] = 2;
for (int i = 3; i * i < MAXN; i++) {
// checking if i is prime
if (spf[i] == i) {
// marking SPF for all numbers divisible by i
for (int j = i * i; j < MAXN; j += i)
// marking spf[j] if it is not
// previously marked
if (spf[j] == j)
spf[j] = i;
}
}
}
// A O(log n) function returning primefactorization
// by dividing by smallest prime factor at every step
vector getFactorization(int x)
{
vector ret;
while (x != 1) {
ret.push_back(spf[x]);
x = x / spf[x];
}
return ret;
}
// Function which returns the minimal
// removals required to make gcd
// greater than previous
int minimumRemovals(int a[], int n)
{
int g = 0;
// finding initial gcd
for (int i = 0; i < n; i++)
g = __gcd(a[i], g);
unordered_map mpp;
// divides all number by initial gcd
for (int i = 0; i < n; i++)
a[i] = a[i] / g;
// iterating for all numbers
for (int i = 0; i < n; i++) {
// primt factorisation to get the prime
// factors of i-th element in the array
vector p = getFactorization(a[i]);
set s;
// insert all the prime factors in
// set to remove duplicates
for (int j = 0; j < p.size(); j++) {
s.insert(p[j]);
}
/// increase the count of prime
// factor in map for every element
for (auto it = s.begin(); it != s.end(); it++) {
int el = *it;
mpp[el] += 1;
}
}
int mini = INT_MAX;
int mini1 = INT_MAX;
// iterate in map and check for every factor
// and its count
for (auto it = mpp.begin(); it != mpp.end(); it++) {
int fir = it->first;
int sec = it->second;
// check for the largest appearing factor
// which does not appears in any one or more
if ((n - sec) <= mini) {
mini = n - sec;
}
}
if (mini != INT_MAX)
return mini;
else
return -1;
}
// Driver code
int main()
{
int a[] = { 6, 9, 15, 30 };
int n = sizeof(a) / sizeof(a[0]);
sieve();
cout << minimumRemovals(a, n);
return 0;
}
Java
// Java program to find the minimum removals
// such that gcd of remaining numbers is more
// than the initial gcd of N numbers
import java.util.*;
class GFG{
static final int MAXN = 100001;
// stores smallest prime factor for every number
static int []spf = new int[MAXN];
// Calculating SPF (Smallest Prime Factor)
// for every number till MAXN.
// Time Complexity : O(nloglogn)
static void sieve()
{
spf[1] = 1;
for(int i = 2; i < MAXN; i++)
// Marking smallest prime factor
// for every number to be itself
spf[i] = i;
// Separately marking spf for every even
// number as 2
for(int i = 4; i < MAXN; i += 2)
spf[i] = 2;
for(int i = 3; i * i < MAXN; i++)
{
// Checking if i is prime
if (spf[i] == i)
{
// Marking SPF for all numbers
// divisible by i
for(int j = i * i; j < MAXN; j += i)
// Marking spf[j] if it is not
// previously marked
if (spf[j] == j)
spf[j] = i;
}
}
}
// A O(log n) function returning primefactorization
// by dividing by smallest prime factor at every step
static Vector getFactorization(int x)
{
Vector ret = new Vector<>();
while (x != 1)
{
ret.add(spf[x]);
x = x / spf[x];
}
return ret;
}
// Recursive function to return gcd of a and b
static int __gcd(int a, int b)
{
return b == 0 ? a : __gcd(b, a % b);
}
// Function which returns the minimal
// removals required to make gcd
// greater than previous
static int minimumRemovals(int a[], int n)
{
int g = 0;
// Finding initial gcd
for(int i = 0; i < n; i++)
g = __gcd(a[i], g);
HashMap mpp = new HashMap<>();
// Divides all number by initial gcd
for(int i = 0; i < n; i++)
a[i] = a[i] / g;
// Iterating for all numbers
for(int i = 0; i < n; i++)
{
// Prime factorisation to get the prime
// factors of i-th element in the array
Vector p = getFactorization(a[i]);
HashSet s = new HashSet<>();
// Insert all the prime factors in
// set to remove duplicates
for(int j = 0; j < p.size(); j++)
{
s.add(p.get(j));
}
// Increase the count of prime
// factor in map for every element
for(int it: s)
{
int el = it;
if (mpp.containsKey(el))
{
mpp.put(el, mpp.get(el) + 1);
}
else
{
mpp.put(el, 1);
}
}
}
int mini = Integer.MAX_VALUE;
int mini1 = Integer.MAX_VALUE;
// Iterate in map and check for
// every factor and its count
for(Map.Entry it : mpp.entrySet())
{
int fir = it.getKey();
int sec = it.getValue();
// Check for the largest appearing factor
// which does not appears in any one or more
if ((n - sec) <= mini)
{
mini = n - sec;
}
}
if (mini != Integer.MAX_VALUE)
return mini;
else
return -1;
}
// Driver code
public static void main(String[] args)
{
int a[] = { 6, 9, 15, 30 };
int n = a.length;
sieve();
System.out.print(minimumRemovals(a, n));
}
}
// This code is contributed by Amit Katiyar
Python3
# Python3 program to find the minimum removals
# such that gcd of remaining numbers is more
# than the initial gcd of N numbers
from math import gcd as __gcd
MAXN = 100001
# stores smallest prime factor for every number
spf = [i for i in range(MAXN)]
# Calculating SPF (Smallest Prime Factor) for every
# number till MAXN.
# Time Complexity : O(nloglogn)
def sieve():
# separately marking spf for every even
# number as 2
for i in range(4, MAXN, 2):
spf[i] = 2
for i in range(3, MAXN):
if i * i > MAXN:
break
# checking if i is prime
if (spf[i] == i):
# marking SPF for all numbers divisible by i
for j in range(2 * i, MAXN, i):
# marking spf[j] if it is not
# previously marked
if (spf[j] == j):
spf[j] = i
# A O(log n) function returning primefactorization
# by dividing by smallest prime factor at every step
def getFactorization(x):
ret = []
while (x != 1):
ret.append(spf[x])
x = x // spf[x]
return ret
# Function which returns the minimal
# removals required to make gcd
# greater than previous
def minimumRemovals(a, n):
g = 0
# finding initial gcd
for i in range(n):
g = __gcd(a[i], g)
mpp = dict()
# divides all number by initial gcd
for i in range(n):
a[i] = a[i] // g
# iterating for all numbers
for i in range(n):
# primt factorisation to get the prime
# factors of i-th element in the array
p = getFactorization(a[i])
s = dict()
# insert all the prime factors in
# set to remove duplicates
for j in range(len(p)):
s[p[j]] = 1
# increase the count of prime
# factor in map for every element
for i in s:
mpp[i] = mpp.get(i, 0) + 1
mini = 10**9
mini1 = 10**9
# iterate in map and check for every factor
# and its count
for i in mpp:
fir = i
sec = mpp[i]
# check for the largest appearing factor
# which does not appears in any one or more
if ((n - sec) <= mini):
mini = n - sec
if (mini != 10**9):
return mini
else:
return -1
# Driver code
a = [6, 9, 15, 30]
n = len(a)
sieve()
print(minimumRemovals(a, n))
# This code is contributed by mohit kumar 29
C#
// C# program to find the minimum
// removals such that gcd of remaining
// numbers is more than the initial
// gcd of N numbers
using System;
using System.Collections.Generic;
class GFG{
static readonly int MAXN = 100001;
// stores smallest prime
// factor for every number
static int []spf =
new int[MAXN];
// Calculating SPF (Smallest
// Prime Factor) for every
// number till MAXN.
// Time Complexity : O(nloglogn)
static void sieve()
{
spf[1] = 1;
for(int i = 2; i < MAXN; i++)
// Marking smallest prime factor
// for every number to be itself
spf[i] = i;
// Separately marking spf for
// every even number as 2
for(int i = 4; i < MAXN; i += 2)
spf[i] = 2;
for(int i = 3; i * i < MAXN; i++)
{
// Checking if i is prime
if (spf[i] == i)
{
// Marking SPF for all numbers
// divisible by i
for(int j = i * i;
j < MAXN; j += i)
// Marking spf[j] if it is
// not previously marked
if (spf[j] == j)
spf[j] = i;
}
}
}
// A O(log n) function returning
// primefactorization by dividing
// by smallest prime factor at
// every step
static List getFactorization(int x)
{
List ret = new List();
while (x != 1)
{
ret.Add(spf[x]);
x = x / spf[x];
}
return ret;
}
// Recursive function to
// return gcd of a and b
static int __gcd(int a,
int b)
{
return b == 0 ? a :
__gcd(b, a % b);
}
// Function which returns the
// minimal removals required
// to make gcd greater than
// previous
static int minimumRemovals(int []a,
int n)
{
int g = 0;
// Finding initial gcd
for(int i = 0; i < n; i++)
g = __gcd(a[i], g);
Dictionary mpp = new Dictionary();
// Divides all number by
// initial gcd
for(int i = 0; i < n; i++)
a[i] = a[i] / g;
// Iterating for all numbers
for(int i = 0; i < n; i++)
{
// Prime factorisation to get the prime
// factors of i-th element in the array
List p = getFactorization(a[i]);
HashSet s = new HashSet();
// Insert all the prime factors in
// set to remove duplicates
for(int j = 0; j < p.Count; j++)
{
s.Add(p[j]);
}
// Increase the count of prime
// factor in map for every
// element
foreach(int it in s)
{
int el = it;
if (mpp.ContainsKey(el))
{
mpp[el]= mpp[el] + 1;
}
else
{
mpp.Add(el, 1);
}
}
}
int mini = int.MaxValue;
int mini1 = int.MaxValue;
// Iterate in map and check for
// every factor and its count
foreach(KeyValuePair it in mpp)
{
int fir = it.Key;
int sec = it.Value;
// Check for the largest appearing
// factor which does not appears
// in any one or more
if ((n - sec) <= mini)
{
mini = n - sec;
}
}
if (mini != int.MaxValue)
return mini;
else
return -1;
}
// Driver code
public static void Main(String[] args)
{
int []a = {6, 9, 15, 30};
int n = a.Length;
sieve();
Console.Write(minimumRemovals(a, n));
}
}
// This code is contributed by Rajput-Ji
Javascript
输出:
2
时间复杂度: O(log log N) 用于预计算 Sieve,O(N * log N) 用于计算。
辅助空间: O(N)