中石油5112: Equal Numbers(贪心模拟)
  Lddcitr3akMp 2023年11月02日 46 0



5112: Equal Numbers


时间限制: 3 Sec   内存限制: 512 MB

提交: 41  

解决: 6

[提交][状态][讨论版][命题人:admin]


题目描述


You are given a list of n integers a1,...,an. You can perform the following operation: choose some ai and multiply it by any positive integer.
Your task is to compute the minimum number of different integers that could be on the list after k operations for all 0≤k≤n.


输入


The first line of the input contains single integer n (1≤n≤3≤105). The second line of the input contains n integers ai (1≤ai≤106).


输出


Output a single line that contains n + 1 integers. The i-th integer should be the minimum possible number of different integers in the list after i-1 operations.


样例输入

6
3 4 1 2 1 2

样例输出

4 4 3 3 2 2 1

【题意】

表示看不懂俄式英语。(题目竟然用some ai, 然后后面用it来代指,我搞不懂出题人从哪个国家学的英语,中国人看不懂)

有n个数,有一种操作:你可以选择其中任意一个数ai ,然后你可以把他乘上一个正整数。

问:当可以执行k次操作时,你可以得到的最小的 “不同数的个数”

【分析】

如果一个数的倍数在序列中出现了,那把他变成这个倍数,最有机会减少不同数目。

否则,只能把它变成他们的最小公倍数,或者不变(相当于乘1)

把每个数及出现次数统计,按出现次数排序,优先变次数少的。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
typedef long long ll;
const int N=1e6+5,mod=1e9+7,INF=0x3f3f3f3f;
 
struct node{
    int x,c;
    friend bool operator<(node a,node b){
        if(a.c==b.c)return a.x<b.x;
        return a.c<b.c;
    }
}st[N],sr[N];
int a[N];
ll c[N];
ll r[N],t[N];
int main()
{
    int n;
    cin>>n;
    rep(i,1,n)scanf("%d",&a[i]),c[a[i]]++;
    int cnt=0,top=0;
 
    ll lcm=1;
    rep(i,1,N-1)if(c[i])
    {
        int flag=0;
        for(int j=i+i;j<N;j+=i)if(c[j]){
            flag=j;
            break;
        }
        if(flag)sr[++cnt]=node{i,c[i]};
        st[++top]=node{i,c[i]};
        if(lcm<N)lcm=lcm*i/__gcd(lcm,(ll)i);
    }
    sort(sr+1,sr+1+cnt);
    sort(st+1,st+1+top);
    rep(i,1,cnt)r[i]=r[i-1]+sr[i].c;
    rep(i,1,top)t[i]=t[i-1]+st[i].c;
    printf("%d",top);
    int last=top;
    for(int i=1;i<=n;i++)
    {
        int ans=last;
        if(i<=r[cnt]){ //可以变为倍数
            int x=upper_bound(r+1,r+cnt+1,i)-r-1;
            ans=min(ans,top-x);
            //cout<<"  "<<x;
        }
        int x=upper_bound(t+1,t+1+top,i)-t-1;
        //cout<<"   "<<x<<endl;
        ans=min(ans,top-x+(lcm!=st[top].x));
        if(i==n)ans=1;
        printf(" %d",ans);
        last=ans;
    }
    cout<<endl;
}


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
Lddcitr3akMp
最新推荐 更多

2024-05-31