Greatest common divisor (two cases)

Let's look at a simple

Contest2274 - Fight against the epidemic, start with me - the fifty-ninth joint training match for primary and secondary school students

Problem A: Greatest Common Divisor
Time Limit: 1 Sec Memory Limit: 128 MB
[commit] [status]

Topic description

Given n numbers, select K from them. Alice wants to make the greatest common divisor of K numbers as large as possible, and finds the greatest greatest common divisor.

enter

The first line contains two positive integers n, K. The second line contains n positive integers, that is, the given n numbers.

output

Output a positive integer representing the greatest greatest common divisor.

Sample input Copy

3 1
1 2 3

Sample output Copy

3

hint

For 30% of the data, n<=20.
For 60% of the data, ensure that all numbers in the input are less than 5000.
For 100% of the data, ensure that all numbers in the input are less than 5e5, K<=n

  • For each question, it is simpler than the next question. This question is done by direct violent enumeration. First, store the number of these numbers in an array, so that it is easy to use, that is, to find the largest number (because the largest number is taken as this When the number of n is the largest, only the largest can be taken)
    and then the sieve is finished.
#include <map>
#include <queue>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <math.h>
typedef long long ll;
using namespace std;
const int maxn=2e6+1010;
#define inf 0x3f3f3f3fconst
int mod=998244353;
const int MOD=10007;

inline int read() {
    
    
	int x=0;
	bool t=false;
	char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}

ll n,t,m,sum,maxx;
ll a[maxn],b[maxn],l[maxn],r[maxn];
char str[500][500],s[maxn];
int main() {
    
    
	cin>>n>>m;
	for(int i=1; i<=n; i++)
		cin>>t,a[t]++,maxx=max(maxx,t);
	for(int i=maxx; i>=1; i--){
    
    
		ll d=0;
		for(int j=i; j<=maxx; j+=i){
    
    
			if(j%i==0) d+=a[j];
		}
		if(d>=m) {
    
    
			cout<<i<<endl;
			return 0;
		}
	}
	return 0;
}


Contest2295 - 2020 Spring Individual Training Game 5

Problem D: Greatest Common Divisor
Time Limit: 1 Sec Memory Limit: 128 MB
[commit] [status]

Topic description

Given n positive integers, a_1, a_2, ..., a_n, find at least a few numbers to be deleted, so that the greatest common divisor of these numbers after deletion is greater than the greatest common divisor of all the original numbers.

enter

The first line contains an integer n, and the second line contains n positive integers, a_1, a_2, ..., a_n.

output

A number, indicating the minimum number of deletions, if it will not be larger than the original no matter how deleted, output -1.

Sample input Copy

3
1 2 4

Sample output Copy

1

hint

By deleting the number 1, the greatest common divisor changes from 1 to 2.
For 30% of the data, n<=15
For 50% of the data, n, a_i<=1000
For 100% of the data, n<=300,000, a_i<=1.5*10^7

  • This question is more difficult than the previous question. One is the data range of this question, and the other is that the deleted greatest common divisor of this question is greater than the original pair of greatest common divisors.

  • In fact, this question is still related to the previous question. The idea of ​​using the previous question is to enumerate and sieve, but this will definitely not be as easy as the previous question, because the amount of data is placed here and there, so it is necessary to optimization.

  • Idea: Find the original greatest common divisor (gcd) This is for sure, (or not, but the constant may be large, for example, if the greatest common divisor is large, the time can be greatly optimized) and then all numbers are Divide by this greatest common divisor (gcd). So it's better to find it, and then find the maximum number as in the previous question, (the maximum number is 1.5e7), and then we think that we can use the sieve method of the previous question, if you want to find the greatest common divisor is to use A number (a) sieve, if these numbers can divide a, then a is their common factor, (not necessarily the greatest common factor) This is equivalent to the prime number sieve, so we only need to sieve outroot maximumThat's alright, the latter is to store these numbers in the array like the previous question. We can know that the maximum number of this number is 1.5e7, so we have no rebate subscript to represent this number, just useIn order to reduce the complexity, sort first, compare the two numbers before and after, and represent two arrays, one for the size of the number, and one for how many times the number appears.This place also maliciously uses structs, the same. The next step is to use the sieve method of the previous question, this time it is whether the sieve can divide these prime numbers. There is a place to pay attention to == some numbers are not in the root maximum after dividing by gcd, and this number is not 1, because 1 is not in the prime numbers we screened out, so it is a separate prime number (greater than the root maximum )== If you don't do this step, you will be stuck at around 91.
    The last is the result, first consider the case of outputting -1.
    Take a look at the code.

#include <map>
#include<iostream>//ÏßÐÔɸËØÊý
#include<math.h>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#define inf 0x3f3f3f3f
const int mod=998244353;
using namespace std;
const int maxn=2e6+10;

map<long long ,long long >mp;
bool a[maxn];
long long f[maxn],flag,cnt;
long long n,m,maxx,sum,b[maxn],c[maxn],e[maxn],d[maxn];

void prime(long long n){
    
    
	for(int i=2;i<=n;i++){
    
    
		if(a[i]==0) f[++cnt]=i;
		for(int j=1;j<=cnt&&i*f[j]<=n;j++)
		{
    
    
			a[i*f[j]]=1;
			if(i%f[j]==0) break;
		}
	}
}


long long  gcd(long long  a,long long b){
    
    
	while(b){
    
    
		long long t=a%b;
		a=b;
		b=t;
	}
	return a;
}

int main(){
    
    
	cin>>n;
	maxx=0;
	for(int i=1;i<=n;i++)
	{
    
    
		cin>>b[i];
		maxx=max(b[i],maxx);
		if(i==1) m=b[i];
		else m=gcd(m,b[i]);
	//	mp[a[i]]++;
	}

	prime(sqrt(maxx/m)+2);
	
	b[0]=0;
	sort(b+1,b+1+n);
	for(int i=1;i<=n;i++)
		if(b[i]!=b[i-1]){
    
    
			++flag;
			d[flag]=b[i]/m;
			e[flag]=1;
		}else e[flag]++;
	
	for(int i=1;i<=flag;i++)
	{
    
    
		long long p=0;
		for(int j=1;j<=cnt;j++)
		{
    
    
			if(d[i]%f[j]==0) c[j]+=e[i],p=1;
		}
		if(p==0&&d[i]!=1){
    
    
			f[++cnt]=d[i];
			c[cnt]+=e[i];
		}
	}
	
	maxx=0;
	for(int i=1;i<=cnt;i++)
		maxx=max(maxx,c[i]);
	if(maxx==n||maxx==0) cout<<"-1"<<endl;
	else cout<<n-maxx<<endl;
	/*
	for(long long i=sqrt(maxx);i>m;i--){
		long long d=0;
		for(long long  j=i;j<=maxx;j+=i)
			if(j%i==0) d+=mp[j];
		if(d>sum){
			sum=d;
		}
	}*/
	
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324883633&siteId=291194637