Gym 101612 Problem E. Equal Numbers

Gym 101612 Problem E. Equal Numbers_第1张图片
题意:
操作是你可以将一个数乘以一个正数。
0 ≤ i ≤ n 0≤i≤n 0in次操作后的最小数字种类数。

思路:
有两种操作,要么是把一种数全部变成他的倍数(尽量大且存在的倍数),要么是将尽量多种类的数变成所有数的公倍数。

那么我们只需要维护出每种数是否存在其倍数,就只能这种数能否进行第一种操作。

只要对每个数因数分解,然后给因数打上标记,就可以知道每个数是否存在其倍数了。复杂度 n t , t n\sqrt{t},t nt t代表数据范围。

#include
#include
#include
#include
#include
#include
#include

typedef long long ll;
using namespace std;
const int maxn = 1e6 + 7;
const int INF = 0x3f3f3f3f;

int a[maxn];
int vis[maxn];
int sum1[maxn],sum2[maxn];

int main() {
     
    freopen("equal.in","r",stdin);
    freopen("equal.out","w",stdout);
    int n;scanf("%d",&n);
    for(int i = 1;i <= n;i++) {
     
        int x;scanf("%d",&x);
        a[x]++;
    }
    for(int i = 1;i <= 1000000;i++) {
     
        if(!a[i]) continue;
        if(a[i] && i != 1) vis[1] = 1;
        int t = sqrt(i);
        for(int j = 2;j <= t + 1;j++) {
     
            if(j == i) continue;
            if(i % j == 0) {
     
                vis[j] = 1;
                vis[i / j] = 1;
            }
        }
    }
    vector<int>vec1; //将数转换为倍数
    vector<int>vec2; //将数转换为所有数的公倍数
    
    for(int i = 1;i <= 1000000;i++) {
     
        if(vis[i] && a[i]) {
     
            vec1.push_back(a[i]);
        }
        if(a[i]) vec2.push_back(a[i]);
    }
    
    sort(vec1.begin(),vec1.end());
    int len1 = vec1.size();
    for(int i = 1;i <= len1;i++) {
     
        sum1[i] = sum1[i - 1] + vec1[i - 1];
    }
    
    sort(vec2.begin(),vec2.end());
    int len2 = vec2.size();
    for(int i = 1;i <= len2;i++) {
     
        sum2[i] = sum2[i - 1] + vec2[i - 1];
    }
    
    sum1[len1 + 1] = INF;
    sum2[len2 + 1] = INF;
    int cnt1 = 1,cnt2 = 1;
    int ans1 = 0,ans2 = 0;
    printf("%d ",len2);
    for(int i = 1;i <= n;i++) {
     
        while(i > sum1[cnt1]) {
     
            cnt1++;
        }
        if(i == sum1[cnt1]) {
     
            ans1 = cnt1;
        } else if(i < sum1[cnt1]) {
     
            ans1 = cnt1 - 1;
        }
        
        while(i > sum2[cnt2]) {
     
            cnt2++;
        }
        if(i == sum2[cnt2]) {
     
            ans2 = cnt2;
        } else if(i < sum2[cnt2]) {
     
            ans2 = cnt2 - 1;
        }
        
        printf("%d ",len2 - max(ans1,ans2 - 1));
    }
    return 0;
}

你可能感兴趣的:(#,gym)