zoukankan      html  css  js  c++  java
  • Equal Numbers Gym

    题意:

    给你n个数vi,你有k次操作。每一次操作你可以从n个数里面挑一个数,然后使得这个数乘于一个正整数。操作完之后,这n个数里面不同数的数量就是权值。你要使得这个值尽可能小。

    题解:

    如果a%b==0 && a!=b

      b%c==0 && b!=c

    那么如果我们进行操作的话,肯定是把c变成a,因为这样消耗的最小操作数最少

    我们最后的答案只需要在两种情况中取最小值就可以了

    1、我们把n个数都往n个数的公倍数上变

    2、如果这n个数里面出现了上面所示的a、b、c的情况,那么我们就把b、c这些数都往a上变

    过程:

    因为题目求的是操作完之后不同数的数量,那么我们首先记录一下每一个数的出现次数

    然后在提前处理一下每一个数的倍数是否在这n个数里面

    然后按照每一个数出现的次数排序。为什么?给你一个序列

    1 1 2 4 

    我们如果只有一个操作,那么肯定是把2变成4.这样的话答案就是2

    这就意味着,我们要使得1变成4的话,那么只有操作数大于等于3的时候才对最后的结果造成影响

    之后就模拟就可以了

    AC代码:

    /*
    有两种操作,要么是把一种数全部变成他的倍数(尽量大且存在的倍数),要么是将尽量多种类的数变成所有数的公倍数。
    
    那么我们只需要维护出每种数是否存在其倍数,就只能这种数能否进行第一种操作。
    
    只要对每个数因数分解,然后给因数打上标记,就可以知道每个数是否存在其倍数了。复杂度n*sqrt(t),t代表数据范围。
    */
    
    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6 + 5;
    const int INF=0x3f3f3f3f;
    const int mod = 1000000007;
    int v[maxn],num[maxn],vis[maxn],que1[maxn],que2[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)
        {
            scanf("%d",&v[i]);
            num[v[i]]++;
        }
        for(int i=1;i<=n;++i)
        {
            int tmp=v[i];
            if(tmp!=1) vis[1]=1;
            int ends=sqrt(tmp);
            for(int j=2;j<=ends;++j)
            {
                if(tmp%j==0)
                {
                    vis[j]=1;
                    vis[tmp/j]=1;
                }
            }
        }
        int pos1=0,pos2=0;
        for(int i=1;i<=1000000;++i)
        {
            if(num[i]==0) continue;
            int tmp=i;
            if(vis[tmp])
            {
                que1[pos1++]=num[tmp];
            }
            que2[pos2++]=num[tmp];
        }
        sort(que1,que1+pos1);
        sort(que2,que2+pos2);
        //printf("%d****%d %d
    ",pos1,que1[0],que1[1]);
        int ans1=0,ans2=0,tmp1=0,tmp2=0;
        printf("%d ",pos2);
        for(int i=1;i<=n;++i)
        {
            tmp1+=1;
            while(tmp1>=que1[ans1] && ans1<pos1)
            {
                tmp1-=que1[ans1];
                ans1++;
            }
    
            tmp2+=1;
            while(tmp2>=que2[ans2] && ans2<pos2)
            {
                tmp2-=que2[ans2];
                ans2++;
            }
    
            if(i!=n)
                printf("%d ",pos2-max(ans1,ans2-1));
            else printf("%d
    ",pos2-max(ans1,ans2-1));
        }
        return 0;
    }
  • 相关阅读:
    [ZJOI2012]灾难
    java实现风险度量
    大字段字符类型
    [CQOI2011]放棋子
    java实现还款计算
    java实现还款计算
    java实现字符串比较
    java实现字符串比较
    快速插入一百万行数据储存过程
    [六省联考2017]分手是祝愿
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13973818.html
Copyright © 2011-2022 走看看