暴力就能答对的题,简单喵!
这个故事是酱紫的
有一个长长的队伍,里面住着好多数字小猫,每个小猫都有自己的颜色(就是数组里的数字)。
主人想把它们排成一个方阵,方阵的每一排有固定的人数,叫 m(列数)。排的顺序是:先排第一排,从左到右,再排第二排……一排一排排下去。
主人想要某一整列的小猫全都变成同一个颜色 k。
咱可以:
- 给某个小猫换颜色(每次改一个数字,花 1 次操作)
- 改变每一排的猫数(增加或减少列数,每次改 1 个,花 1 次操作)
问:最少需要多少次操作?
咱来一步步说喵!
① 读入数据
- n:队伍里一共有多少小猫。
- m:现在每排站几个猫(初始的列数)。
- k:想要他们变成的颜色。
- num 数组:每个小猫现在的颜色。
② 尝试“增加每排猫数”
咱们先看看,如果让每排站更多的猫(列数变大),会不会更省事。
从现在的 m 开始,一直试到最多 n(因为每排人数不能超过队伍总人数,否则一排就站完啦)。
对于每一种“每排猫数” i,总代价是:
- 换衣服次数 = num_cost(i)(详见以下喵)
- 换排数次数 = i - m(因为从 m 增加到 i,需要 i-m 次操作)
总代价 = 换衣服次数 + 换排数次数。
然后咱用 ans 记录最小的总代价。
但是,这里有一个聪明的小窍门(剪枝):
如果光是增加排数这一步 i - m 已经比当前找到的最优答案 ans 还要大了,那继续增加排数只会让这一步更大,肯定得不到更小的答案,所以咱就提前结束循环啦。
这就是 i - m < ans 的作用喵。
③ 尝试“减少每排猫数”
类似地,从 m-1 往下试,直到每排最少 1 个猫。
总代价 = num_cost(i) + (m - i)。
剪枝条件 m - i < ans 也一样:如果减少排数这一步已经比当前答案大了,就不用再试更小的 i 了。
num_cost(new_m) —— 看看每排站多少猫时最省事
咱来解释喵!
这个函数就是帮咱算出:如果每排站 new_m 个小猫,那至少要给几个小猫换衣服,才能让某一整列全都变成目标颜色 k。
咱要检查每一列:
- 第 0 列:下标是 0, new_m, 2*new_m, …(也就是第一排第一个、第二排第一个……)
- 第 1 列:下标是 1, 1+new_m, 1+2*new_m, …
- 一直到第 new_m-1 列。
对每一列,数一数有多少个小猫不是颜色 k,那就是这一列需要换的猫数喵。
然后咱从所有列里挑一个最小的,这就是在 new_m 列下最少要换的猫数啦。
举个例子喵!
队伍颜色:1 2 3 1 2 3,目标 k=2,每排站 3 个人。
第 0 列(下标 0,3):1 1 → 需要换 2 个
第 1 列(下标 1,4):2 2 → 需要换 0 个
第 2 列(下标 2,5):3 3 → 需要换 2 个
所以最少需要换 0 个,函数就返回 0 喵。
主人奇怪的需求就美美完成啦喵!
看代码喵!
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
vector<ll> num(2e5);
ll n,m,k;
ll num_cost(ll new_m)
{
ll now_ans=1e9;
for(ll i=0;i<new_m;i++)// 看第 i 列
{
ll one=0;// 这一列要换颜色的小朋友数量
for(ll j=i;j<n;j+=new_m)
{
if(num[j]!=k) one++;// 如果颜色不是 k,就得换
}
now_ans=min(now_ans,one);// 记录这一列需要换的最少人数
}
return now_ans;
}
void solve()
{
ll ans=1e9;
cin >> n >> m >> k;
for(ll i=0;i<n;i++) cin >> num[i];
// 尝试增加每排人数(从 m 往上加)
for(ll i=m;i<=n&&i-m<ans;i++)
{
ans=min(ans,num_cost(i)+i-m);
}
// 尝试减少每排人数(从 m 往下减)
for(ll i=m-1;i>0&&m-i<ans;i--)
{
ans=min(ans,num_cost(i)+m-i);
}
cout << ans << '\n';
}
int main() {
cin.tie(0)->sync_with_stdio(0);
int T;cin >> T;
while (T--) solve();
}
/*
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣤⡀⣀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⡀⢀⣴⣾⣷⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣷⣾⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⠿⠛⠛⠉⠉⠉⠉⠉⠉⠛⠻⠿⣿⣿⣿⣿⣿⣶⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⡿⠿⠛⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠿⣿⣿⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣀⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⣰⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣠⣾⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣶⣄⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣻⣿⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢹⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⠁⠈⢢⡀⠀⠀⠀⢸⡇⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⡟⠒⢦⡀⠀⠀⠀
⠀⠀⣠⣤⣤⣼⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡇⠀⠀⠀⠉⢢⣄⠀⠀⢿⠊⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣷⡄⠀⢷⠀⠀⠀
⠀⢰⠇⠀⣰⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⡌⣹⠗⠦⣬⣇⠀⠉⢢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡀⢸⡄⠀⠀
⠀⡟⠀⣼⣯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣆⢹⡀⠀⠀⠀⠉⠁⠀⠀⢀⣀⡁⠀⠀⠉⠳⢴⡆⠀⠀⠀⠀⠀⠀⢹⣧⠈⡇⠀⠀
⠀⡇⠀⠀⢻⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣾⠻⠉⠛⠂⠀⠀⠀⠀⠀⠀⠻⠿⣿⣿⣿⣶⣦⡀⠛⣇⠀⠀⠀⠀⠀⣈⣿⠀⡇⠀⠀
⢸⡇⠀⠀⢠⣿⣷⣦⣀⡸⣷⣦⣶⡂⠉⠉⠉⢁⣤⣶⡶⠀⠀⠀⣀⣀⡴⠀⠀⠀⠀⠀⠀⠈⠉⠉⠁⠀⡟⢀⣴⣟⣰⣾⣿⣏⣠⠇⠀⠀
⠈⡇⠀⠀⢸⣿⠁⠉⣿⠛⠛⠃⡇⠀⠀⢠⣶⣿⡿⠛⠁⠀⠀⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⢿⠟⠿⢿⡏⠀⠘⣿⡀⠀⠀⠀
⠀⢷⣀⣀⣿⠇⠀⠀⢿⡇⠀⢀⢱⡀⠀⠛⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠀⠀⢸⠇⠀⠀⢹⣿⣄⠀⠀
⠀⠀⣉⣿⡏⠀⠀⠀⠀⠀⠀⢸⣇⣳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⣿⠃⠀⠀⠀⠀⠀⠀⣿⠈⢧⠀
⠀⠘⣿⣿⠁⠀⠀⠀⠀⠀⠀⠘⣿⡛⣶⠀⠀⣠⠔⠒⠛⠒⠦⡀⠀⠀⠀⠀⣠⡤⠶⠤⢤⣀⠀⠀⠀⢀⣏⡄⠀⠀⠀⠀⠀⡀⣿⡆⠈⣧
⣠⡾⠛⣿⣿⣧⠀⠀⠀⠀⢸⣿⠾⢿⡿⠀⣰⠃⠀⠀⠀⠀⠀⢹⡄⠀⠀⡼⠁⠀⠀⠀⠀⠈⠙⣦⠀⢸⣿⡇⣾⣣⡀⠀⢰⣿⣿⣿⣤⠾
⡟⠀⠀⠻⣿⡟⢷⡄⣤⡀⠈⣿⡀⣸⠇⠀⠏⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⡇⢀⡀⠀⠀⠀⠀⢀⡟⠀⠀⠋⣿⣿⣿⡇⣠⣿⠿⠛⢷⡀⠀
⠀⠀⠀⠀⣿⣇⣨⣿⣿⣿⣦⣽⣷⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠃⠀⠙⠢⠤⠤⠴⢾⠀⠀⠀⠀⢸⣷⣿⣿⠟⠁⠀⠀⠈⣧⠀
⠀⠀⠀⠀⠈⠉⠉⠁⠈⠉⠈⢉⣿⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⢸⡇⠀⠀⠀⠀⠀⠀⠀⣿⠀
*/

京公网安备 11010502036488号