1 条题解
-
0
自动搬运
来自洛谷,原作者为

WindowsWKP
互关!||100粉随便问5个问题||主页https://www.luogu.com.cn/paste/ivzwecet|@syd190214还号搬运于
2025-08-24 22:57:10,当前版本为作者最后更新于2024-04-20 08:00:06,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
Update On 4.25:修改为全角符号。
Update On 5.5:代码全部修改为
scanf和printf。(避免剪枝部分歧义)Update On 7.28:“剪枝”板块改为“优化”板块。
分析
这道题目最基础的枚举思路是:
-
用桶 存下每一种邮票出现的数量。
-
从 到 枚举 。
-
从 到 判断 共有几张可用的邮票。
-
合成答案,输出结果。
但由于 太大,无法存下太大的桶,所以一个简单的处理方式就是离散化,代码 分。
#include<bits/stdc++.h> using namespace std; int a[300010],n,k,x,y,f[300010],ans; int main(){ cin>>n; for (int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+n+1); for (int i=1;i<=n;i++){ if (a[i]!=y) x++,y=a[i]; a[i]=x; } for (int i=1;i<=n;i++) f[a[i]]++; for (k=1;k<=n;k++){ ans=0; for (int i=1;i<=n;i++) if (f[i]>=k) ans+=f[i]-f[i]%k; cout<<ans<<" "; } return 0; }优化
这种代码需要排序,又有大规模枚举,必须要优化。
-
使用
printf代替cout,代码 分。 -
将 改为数组,如果 已经是 了,就没有继续枚举的必要了。虽然还是 分,但子任务 开始出现很多通过的点了。
-
边离散化边装桶,代码还是 分,但仍有较小提升,且更为简洁。
-
判断 时,只判断 到 ,因为装了东西的桶只有 个。代码 分,只剩下 个点。
-
对桶进行排序,并在判断 时,如果发现桶已经无法取出邮票了,就停止判断。代码 分,且有极大余量。
代码
#include<bits/stdc++.h> using namespace std; int a[300010],n,k,x,y,f[300010],ans[300010]={1}; int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); for (int i=1;i<=n;i++){ if (a[i]!=y) x++,y=a[i]; a[i]=x; f[a[i]]++; } sort(f+1,f+x+1); for (k=1;k<=n;k++){ ans[k]=0; if (ans[k-1]==0) break; for (int i=x;i>=1;i--){ if (f[i]>=k) ans[k]+=f[i]-f[i]%k; else break; } printf("%d ",ans[k]); } for (k=k;k<=n;k++) printf("0 "); return 0; } -
- 1
信息
- ID
- 10064
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 2
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者