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 ...
随机推荐
- 创建多线程方式(Java)
一.创建自定义线程类继承Thread 自定义线程类代码 package com.demo05; public class MyThread extends Thread { @Override pub ...
- How to 充分利用你的服务器
服务器高性能计算指南 本文处于preview阶段,内容并不完全严谨,如有错误敬请原谅,适当参考. 目录 服务器高性能计算指南 什么样的计算适合当前服务器? 从CPU架构入手 两个CPU带来的影响 那么 ...
- 基于protobuf和httplib的在线通讯录项目框架|Protobuf应用小项目
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量博客汇总https://blog.cs ...
- ZR 七连 Day 1 游记
ZR 七连 Day 1 游记 游记篇 赛前搞笑事件 今天是第一场正睿,还是要 好好对待 的 $ 17:59:58 $ 还在吃饭 $ 17:59:59 $ 做出重要决定,先打着比赛,有空就吃一口包子 $ ...
- delphi 异常测试(我自己捕捉)
由于最近的短信模块老是报SocketErorr错误,有的时候也不确定是哪里有问题,影响短信的销售,所以这里这样写,把出现的异常捕捉到显示出来.然后跳过这个不发送 ------------------- ...
- C++文件输入输出的简单实现(Debug)
1.前言: 文件输入输出是个很有用的东西,有时比赛时要有:要求使用文件输入输出,还有时候-- 遇到这种时间限制非常恶心的题目:手动测试会有误差-- 文件输入输出是个很好的选择! 2.写法: C C语言 ...
- JS leetcode 杨辉三角Ⅱ 题解分析
壹 ❀ 引 今天是的题目来自leetcode的119. 杨辉三角 II,还记得几天前,我第一次遇到118. 杨辉三角,一段代码调试半天写不出来,这次遇到升级版终于开开心心快快乐乐轻松解题,题目描述如下 ...
- PCIE详解
老男孩读PCIe之一:从PCIe速度说起 从今天开始,老男孩要开始讲PCIe了.对我来说,这是个很大的挑战:首先,我自己本身,对PCIe并没有做到胸有成竹,我的PCIe知识也只是停留在理论阶段,我并没 ...
- 【framework】TaskStack简介
1 前言 TaskStack 用于管理 app,一般一个应用程序对应一个 TaskStack,其父容器为 TaskStackContainers(DisplayContent 的子容器),子容器为 ...
- Vue+SpringBoot+ElementUI实战学生管理系统-4.后端API编写
1.章节介绍 前一篇介绍了项目的表结构设计,这一篇编写后端API,需要的朋友可以拿去自己定制.:) 2.获取源码 源码是捐赠方式获取,详细请QQ联系我 :)! 3.项目截图 登录页 列表操作 动态图 ...