Codeforces Round #844:C. Equal Frequencies
一、来源:Problem - C - Codeforces
二、题面
三、思路
先考虑一个子问题模型:我们现在有用\(m_1\)种随机字母组成的n个数,各字母个数未定,现在需要使这n个数变为\(m_2\)种类,平均每个种类为blance=n/\(m_2\)个数,问如何求得最小的改变数
显然,只能由多的数向少的数改变,为此我们先尝试求出所有所有字母出现的次数并对其进行降序排序得到
vector<pair<int,int>> v;\\pair的first为字母小标(由0开始),second为字母出现的个数
我们考虑转换的过程,其实就是较高位-1,较低位+1的过程.
- 尝试只找需要减去的位,初一看我们在前面高位用
v[i].second
减去blance直到v[i].second<=blance
即可,然而事实上这情况讨论过的前提是\(m_1<m_2\);当\(m_1>m_2\),以数列9,3,3,3,2为例,我么将其转为为5,5,5,5,
,最前面的9需要减去,后面的2也需要减去,这就比较复杂了 - 尝试只找需要增加的位:根据上面错误的经验,我们可以得到需要增加的部分都是在m2之前的,且都可以使用表达式
ans+=blance-v[i].second
.经代码验证可以得到复合题意的解
- 尝试只找需要减去的位,初一看我们在前面高位用
code
#include<bits/stdc++.h> using namespace std; bool cmp(const pair<int,int> a,pair<int,int> b){
return a.second > b.second;
} char toChar(int offset){
return 'a'+offset;
} int toInt(char c){
return c-'a';
} int main(){
int t;
cin >> t;
while(t--){
int n,m2; //n个数转换为m种,每种n/m个
char str[100];
cin >> n >> m2;
cin >> str;
map<int,int> mp;
for(int i=0;i<26;i++){ //需初始化
mp[i]=0;
}
int m1=0;
for(int i=0;i<n;i++){
if(++mp[toInt(str[i])]==1){
m1++;
}
}
vector<pair<int,int>> v(mp.begin(),mp.end());
sort(v.begin(),v.end(),cmp);
int ans=0,blance=n/m2;
for(int i=0;i<m2;i++){
if(v[i].second<blance){
ans+=blance-v[i].second;
}
}
cout << ans << endl;
}
return 0;
}
注:该问题模型其实还可以简化为:n个和为sum的数,每次加一减一,通过加减操作转化为m个相同的数,每个数为sum/m,所需要的最少加减次数
将问题分解:本题注意到小写字母是可以遍历的,我们可以遍历26种可能的情况求得变化最小的一次解的值,然后再对字符串进行变换
- 遍历26种可能并求得变化最小的一个解
- 模拟求变换即可(这里的代码属于是暴力了)
补充:对于
toChar
,toInt
,最好还是封装为函数
四、代码
#include <bits/stdc++.h>
#define eleType int
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
//字母遍历
//设字母总数为n,平等值为m => n<26*m且n%m==0
const int N=1e5+10;
char arr[N];
map<int,int> mp;
bool cmp(const pair<int,int> a,pair<int,int> b){
return a.second > b.second;
}
char toChar(int offset){
return 'a'+offset;
}
int toInt(char c){
return c-'a';
}
int main(){
int t;
cin >> t;
while(t--){
eleType n;
cin >> n >> arr;
for(int i=0;i<26;i++){ //需初始化
mp[i]=0;
}
int m1=0;
for(int i=0;i<n;i++){
if(mp[toInt(arr[i])]++==0){
m1++;
}
}
vector<pair<int,int>> v(mp.begin(),mp.end());
sort(v.begin(),v.end(),cmp);
eleType ans=INF,m2=1,blance;
for(int i=1;i<=26;i++){
if(n%i==0){ //i是种类,不是个数,不需要保证26*i>=n
// cout << "i:" << i << endl;
eleType temp=0,now=0;
blance=n/i;
for(int j=0;j<i;j++){
//cout << "mp[" << j << "]:" << mp[j] << endl;
if(v[j].second<blance){
temp+=blance-v[j].second;
}
}
// cout << temp << endl;
if(temp<ans){
ans=temp;
m2=i;
}
// cout << "i:" << i << " temp:" << temp << endl;
}
}
blance = n/m2;
eleType next=0;
for(int i=0;i<v.size();i++){
if(v[i].second<blance){
next=i;
break;
}
}
// cout << m2 << endl;
for(int i=0;i<n;i++){
eleType now;
for(int j=0;j<v.size();j++){
if(arr[i] == toChar(v[j].first)){ //易错漏,转换应封装为函数
now=j; //排序后的位置
}
}
if(v[now].second>blance||now>=m2){ //多余数,后者所在的种类位次超过m2
//在前面或后面
v[now].second--;
// cout << "v[next].first:" << v[next].first << endl;
arr[i]=toChar(v[next].first);
if(++v[next].second==blance){
next++;
}
}
}
cout << ans << endl;
cout << arr << endl;
}
return 0;
}
Codeforces Round #844:C. Equal Frequencies的更多相关文章
- Codeforces Round #844 (Div.1 + Div.2) CF 1782 A~F 题解
点我看题 A. Parallel Projection 我们其实是要在这个矩形的边界上找一个点(x,y),使得(a,b)到(x,y)的曼哈顿距离和(f,g)到(x,y)的曼哈顿距离之和最小,求出最小值 ...
- Codeforces Round #844 (Div. 1 + Div. 2, based on VK Cup 2022 - Elimination Round) A-D
比赛链接 A 题意 设计一条线路要贴着6个墙面走,从 \((a,b)\) 到 \((f,g)\) ,线路长度最短. 题解 知识点:模拟. 分类取最短即可. 时间复杂度 \(O(1)\) 空间复杂度 \ ...
- cf之路,1,Codeforces Round #345 (Div. 2)
cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅..... ...
- Codeforces Round #262 (Div. 2) 1003
Codeforces Round #262 (Div. 2) 1003 C. Present time limit per test 2 seconds memory limit per test 2 ...
- Codeforces Round #284 (Div. 2)A B C 模拟 数学
A. Watching a movie time limit per test 1 second memory limit per test 256 megabytes input standard ...
- Codeforces Round #270 1003
Codeforces Round #270 1003 C. Design Tutorial: Make It Nondeterministic time limit per test 2 second ...
- Codeforces Round #270 1002
Codeforces Round #270 1002 B. Design Tutorial: Learn from Life time limit per test 1 second memory l ...
- Codeforces Round #285 (Div. 2) A B C 模拟 stl 拓扑排序
A. Contest time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset (0/1-Trie树)
Vasiliy's Multiset 题目链接: http://codeforces.com/contest/706/problem/D Description Author has gone out ...
- Codeforces Round #367 (Div. 2) C. Hard problem(DP)
Hard problem 题目链接: http://codeforces.com/contest/706/problem/C Description Vasiliy is fond of solvin ...
随机推荐
- 我管你什么okr还是kpi,PPT轻松交给你
word一键转ppt 通过[文件]→[选项]→[快速访问工具栏],选择[不在功能区中的命令],找到[发送到Microsoft PowerPoint ],单击[添加]后再[确定] 调出功能按钮后,就可以 ...
- SpringCloud-03-Nacos配置管理
Nacos配置管理 原理图: 1.统一配置管理 ① 在Nacos中添加配置信息 ② 在弹出表单中填写配置信息 ③ 配置获取的步骤*(原理) ④ 引入Nacos的配置管理客户端依赖 <!--nac ...
- C#使用Tamir.SharpSsh.jsch上传文件异常Algorithm negotiation fail
环境 服务器:centos6.5 客户端:Windows 前言 项目中有一个exe,安装在客户端,其中有一个功能是将本地产生的文件上传至服务器,这个功能是以服务的方式安装在客户端上.之前一切好使,文件 ...
- java在服务器上创建文件(以shell脚本为例)并执行
java在服务器上创建文件(以shell脚本为例)并执行 1️⃣ 首先写个方法,来在服务器上创建脚本 package com.preciouslove.xinxin_emo.controller; i ...
- P4747 [CERC2017] Intrinsic Interval 题解
题目链接:Intrinsic Interval 讲讲析合树如何解决这种问题,其实这题很接近析合树的板题的应用. 增量法进行析合树建树时,需要用 ST 表预处理出 \(max\) 和 \(min\) 以 ...
- 一行命令找出 Linux 中所有真实用户
哈喽大家好,我是咸鱼. 接触过 Linux 的小伙伴们都知道在 Linux (或者说类 Unix)中,有三种类型的用户: 超级用户(UID 为 0):即 root 用户,拥有最高权限. 系统用户(UI ...
- angularjs国际化多语言,angular-translate教程详解,$translate.instant()为什么不生效
壹 ❀ 引 最近项目要求支持国际化多语言,由于项目用的还是angularjs,那么首当其冲的选择了angularjs封装的I18N插件angular-translate,本文主要会从三个方向展开讨论, ...
- Ubuntu/Centos 管理员权限获取
OS:Ubuntu 18.04.1 打开Terminal; 输入命令:sudo su; 屏幕上会回显要求输入当前用户密码的提示,输入密码即可获得管理员权限; 若想退出管理员权限可输入命令:su 用户名 ...
- pip指定镜像安装
清华大学开源软件镜像站
- 【OpenGL ES】绘制魔方
1 前言 在立方体贴图(6张图)中,绘制了一个立方体,贴了 6 张图,本文的魔方案例,将实现绘制 27个立方体,贴 162 张图.贴图图片如下: 说明:inside.png 为魔方内部色块,用 ...