http://codeforces.com/contest/1047/problem/C
Title:
Give you an array, let you delete the minimum number, make the new array GCD > the original array.
POINT:
What to do in the game: (countless TLE, wa and various SB mistakes)
Find the gcd of the original array, and update each element of the original array to a[i]/gcd
In this way, we are factoring the array. For example, 45 = 3 * 3 * 5. So the number of 45 is one contribution for each of 3 and 5.
The most important contribution of prime factor is to delete the least number and get gcd = Original gcd * prime factor. It must be bigger than the original array.
The common way to decompose the prime factor is o(sqrt(x)). So the extreme case is 3e5*sqrt(1.5e7), which must be timed out.
Make a prime table. It's faster, but it's still out of time. When decomposing the prime factor, we can directly judge whether the number is prime or not. If it is, we don't need to cycle.
The card is over.
#include <iostream> #include <stdio.h> #include <queue> #include <string.h> #include <math.h> #include <algorithm> using namespace std; #define LL long long const int N = 3e5+4; const int M =1000000; const int maxn = 15000000+33; int a[N]; int mp[maxn],mp1[maxn]; int num[maxn]; int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } int tag[maxn]; int prime[M]; int cnt=0; void Prime(){ memset(tag,0,sizeof(tag)); tag[0]=tag[1]=1; for(int i = 2; i<maxn; i++){ if(!tag[i]) prime[cnt++]=i; for(int j=0;j<cnt && prime[j]*i<maxn; j++){ tag[i*prime[j]] = 1; if(i % prime[j]==0) break; } } } int k=0; void ff(int x) { for(int i=0;i<cnt&&prime[i]<=x;i++){ if(tag[x]==0) break; int j=prime[i]; if(x%j==0){ mp1[j]=0; while(x%j==0){ mp1[j]++; x/=j; } num[j]++; if(k<num[j]){ k=num[j]; } } } if(x>1){ num[x]++; if(k<num[x]){ k=num[x]; } } } int main() { Prime(); int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } int x=gcd(a[1],a[2]); for(int i=3;i<=n;i++){ x=gcd(x,a[i]); } for(int i=1;i<=n;i++){ ff(a[i]/x); } if(k==0) printf("-1\n"); else printf("%d\n",n-k); }
There is also a simple way: efficiency is not bad.
It's better to update the original array. That is a[i]=a[i]/gcd.
Then simulate the method of prime number ordinary sieve. Record that each prime number exists in several numbers. O(n*loglog(n)) n=1.5e7.
There seems to be a linear screen. I don't understand.
#include <iostream> #include <stdio.h> #include <queue> #include <string.h> #include <math.h> #include <algorithm> using namespace std; #define LL long long const int N = 3e5+4; const int M = 15000000+33; int a[N]; int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } int num[M]; int p[M],cnt=0,flag[M]; int main() { int n;scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int x=a[1]; for(int i=2;i<=n;i++) x=gcd(x,a[i]); for(int i=1;i<=n;i++){ num[a[i]/x]++; } int ans=0; for(int i=2;i<M;i++){ if(flag[i]==0){ int cnt=0; for(int j=i;j<M;j+=i){ flag[j]=1; cnt+=num[j]; } ans=max(ans,cnt); } } if(ans==0) printf("-1\n"); else printf("%d\n",n-ans); }