1. 程式人生 > >Codeforces Round #511 (Div. 2) C. Enlarge GCD (質因數)

Codeforces Round #511 (Div. 2) C. Enlarge GCD (質因數)

 

題目

 

題意:

  給你n個數a[1]...a[n],可以得到這n個數的最大公約數, 現在要求你在n個數中 儘量少刪除數,使得被刪之後的陣列a的最大公約數比原來的大。 如果要刪的數小於n,就輸出要刪的數的個數, 否則輸出 -1 。

 

思路:

  設原來的最大公約數為 g, 然後a[1]...a[n]都除以g ,得到的新的a[1]...a[n],此時它們的最大公約數一定是1 。

  設除以g之後的陣列a為: 

              1    2    3     6      8   10

   則它們的質因數分別是:  1    2    3    2 3    2    2 5

  其中 質因數 2 的次數出現的最多,出現了4 次, 所以我們只要刪除 n-4=2 個數就能使最大公約數由1 變成 2 。即刪除 a[1]和a[3]就好,答案就是 2 。

  綜上,只要找出質因數出現的最多的次數d, n-d就是我們要的答案。

 

  程式碼實現過程中,由於資料較大,要把篩質數 和 選因子  分開來做, 不能同時篩質因子(會超時),因為要避免篩質數這部分重複(打一次表就好)。  篩質數的時候,用2000以內的質數就夠了(我也不知道為什麼!)

  順便一提:一個數m 的因子個數k 是小於log2m的 , 因為2^k<m 。 還有 陣列至少能開1.5e7 大 。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include <cctype>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cmath>
 7 #include<string>
 8 #include<cmath>
 9
#include<set> 10 #include<vector> 11 #include<stack> 12 #include<queue> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define mem(a,x) memset(a,x,sizeof(a)) 17 #define se second 18 #define fi first 19 const ll mod=1e9+7; 20 const int INF= 0x3f3f3f3f; 21 const int N=3e5+5; 22 23 24 const int N2=1.5e7+5; 25 int n; 26 int cnt=0; 27 int check[2005]; 28 int a[N]; 29 int num[N2]; 30 int prime[N]; 31 32 33 int gcd(int x, int y) 34 { 35 return y==0?x:gcd(y,x%y); 36 } 37 void _prime() 38 { 39 int m=2000; 40 for(int i=2;i<=m;i++) //N以內的質數 41 { 42 if(!check[i]) 43 { 44 prime[++cnt]=i; 45 for(int j=i;j<=m;j+=i) 46 { 47 check[j]=1; 48 } 49 } 50 } 51 } 52 void factor(int m) 53 { 54 for(int i=1;i<=cnt;i++) 55 { 56 if(m%prime[i]==0) 57 num[prime[i] ]++; 58 while(m%prime[i]==0) 59 { 60 m/=prime[i]; 61 } 62 } 63 if(m!=1) //包括了1 64 num[m]++; 65 } 66 67 int main() 68 { 69 cin>>n; 70 for(int i=1;i<=n;i++) 71 scanf("%d",&a[i]); 72 73 int g=a[1]; //g=刪除前的最大公約數 74 for(int i=2;i<=n;i++) g=gcd(g,a[i]); 75 76 _prime(); 77 for(int i=1;i<=n;i++) 78 { 79 a[i]/=g; 80 factor(a[i]); 81 } 82 83 int ans=INF; 84 for(int i=1;i<=N2;i++) 85 { 86 if(num[i]) 87 ans=min(ans,n-num[i]); 88 } 89 cout<< (ans<n? ans:-1 )<<endl; 90 }
View Code