1. 程式人生 > >Codeforces1034A. Enlarge GCD

Codeforces1034A. Enlarge GCD

題目連結:http://codeforces.com/problemset/problem/1034/A
題目大意:給出n個數,他們有一個最大公因子x,現在可以剔除n個數中的k個數,求一個最小的k,使得剔除之後的(n-k)個數的最大公因子大於x。

分析:首先求出n個數的最大公因子x,再把這個最大公因子從這n個數中剔除(n/x),餘數y=(n/x),將y所在位置標記cnt++,表示這個位置有cnt個y,和素數篩原理一樣,接下來篩數,將i倍數地方的cnt全部相加,表示n個數中有因子i的個數,儲存最大個數。

程式碼:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int MAXN = 2e7+7;
int a[MAXN],cnt[MAXN];
bool vis[MAXN];


int main()
{
    int n;
    memset(vis,true,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    scanf("%d", &n);
    int x,ans;
    scanf("%d", &x);
    a[0] = x;

    for(int i = 1; i < n; i++)//求所有數的最大公約數
    {
        scanf("%d", &a[i]);
        x = __gcd(x,a[i]);
    }
    for(int i = 0; i < n; i++)
    {
        cnt[a[i]/x]++;//縮小x倍
    }
    vis[0] = vis[1] = false;
    ans = 0;
    for(int i = 2; i < MAXN; i++)//篩子,同素數篩原理,找出含有公共因子個數最多的組合,記為ans
    {
        int res = cnt[i];
        if(vis[i])
        {
            for(int j = 2*i; j < MAXN; j+=i)
            {
                vis[j] = false;
                res+=cnt[j];
            }
        }
        ans = max(ans,res);
    }//含有相同單個因子的數最多有ans個,輸出需要剔除的
    printf("%d\n", ans==0?-1:n-ans);


    return 0;
}