T2:集合

分析:

    显而易见的是 ,如果依照题意进行模拟操作,会发现,很难确定终点。    

  此时可以应用逆向思维,对每个数进行反向运算。

  即,操作变为对集合中的每个数x:  

1. x=x-1
2. 合并两个数 a,b x=a+b
3. 不对x进行操作

复杂度:

  时间复杂度:O(n log n)

  空间复杂度:O(n)

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1e7+7;
int N,Ans,T[maxn],X[maxn];
inline int Read(void)
{
    int x=0,w=0;
    char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
    return w?-x:x;
}
bool CMP(const int A,const int B)
{
    return A>B;
}
int main(void)
{
    N=Read();
    for(int i=1; i<=N; ++i)
    {
        T[i]=Read();
        ++X[T[i]];//统计每个数字出现次数 
    }
    sort(T+1,T+1+N,CMP);//PS:逆向操作 
    int Z=X[0];
    for(int i=1; i<=T[1]; ++i)//把每个数清零  
    {
        ++Ans;//累计轮数 
        Z=(Z+1)/2;///合并数字 
        Z+=X[i];//增加新数字 
    }
    for(Z; Z>1; Z=(Z+1)/2) ++Ans;//记录合并剩余数字次数 
    printf("%d",Ans);
    return 0;
}

 


    

posted @ 2019-07-27 19:59  星空泪  阅读(159)  评论(0编辑  收藏  举报