Enlarge GCD【Codeforces Round #511 (Div. 2)】【素數篩思想】
阿新 • • 發佈:2018-12-11
題目連結
思路:
這道題的思路取自素數篩,甚至是尤拉篩,我們要刪除一些數字,使得gcd增長,那麼,我們就得把除去公共gcd之後的數進行一次篩選,從最小的開始,我們求出那些個有相同質因數的數的數量的最大值。
舉個例子: 對於2 4 4 8 8 ; 他們的gcd==2, 除以2以後:1 2 2 4 4,我們從2開始遍歷“1~maxn”, 發現有4個是2的倍數,所以我們刪除的是N-4==1。
或許一個例子不夠形象: 對於3 6 6 9 ; 它們的gcd==3, 除以3以後:1 2 2 3,我們從2開始,2個是2的倍數, 1個是3的倍數,之後5、7、11......沒有這樣的數了,所以刪除N-2==2即可。
思路就是這樣的。
特殊的,對於除完之後只剩下“1,1,1,1,......”這樣的數,我們直接printf("-1\n")。
完整程式碼:
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef long long ll; const int maxN=300005; const int maxA=15000005; int N, tree[maxN<<2], a[maxN], cnt[maxA]; bool vis[maxA]; int gcd(int a, int b) { return b==0?a:gcd(b, a%b); } void buildTree(int rt, int l, int r) { if(l==r) { scanf("%d", &a[l]); tree[rt]=a[l]; return; } int mid=(l + r)>>1; buildTree(rt<<1, l, mid); buildTree(rt<<1|1, mid+1, r); tree[rt]=gcd(tree[rt<<1], tree[rt<<1|1]); } int main() { while(scanf("%d", &N)!=EOF) { buildTree(1, 1, N); memset(cnt, 0, sizeof(cnt)); int dislike=tree[1]; int ans=0, sum=0; for(int i=1; i<=N; i++) { a[i]/=dislike; cnt[a[i]]++; } memset(vis, false, sizeof(vis)); for(int i=2; i<maxA; i++) { if(!vis[i]) { ans=0; for(int j=i; j<maxA; j+=i) { ans+=cnt[j]; vis[j]=true; } } sum=max(sum, ans); } if(sum==0) printf("-1\n"); else printf("%d\n", N-sum); } return 0; }