这个问题类型以前没学过,记一下
P1031 [NOIP2002 提高组] 均分纸牌
https://www.luogu.com.cn/problem/P1031
显然最后均分完纸牌后,各个堆的纸牌数量均为平均数avg
考虑一个堆一个堆处理
如果a[i] == avg,则这个堆已经满足 不用处理
否则,则需要将(a[i] - avg)加到a[i + 1]上(表示把牌放到i+1那个堆或者从i+1那个堆拿牌),同时数量增加
这里移动若干张纸牌就算1次 如果移动x张就算x次操作的话,就能发现其实就是求|a[i] - avg|的前缀和
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int n, a[110], d[110], sum, ans, avg;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];
}
avg = sum / n;
for (int i = 1; i < n; i++)
{
if (a[i] == avg)
continue;
a[i + 1] += (a[i] - avg);
ans++;
}
cout << ans;
return 0;
}
P2512 [HAOI2008] 糖果传递
https://www.luogu.com.cn/problem/P2512
环形均分纸牌问题
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int N = 1e6 + 10;
int n;
LL a[N], c[N], sum, avg;
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];
}
avg = sum / n;
for (int i = 1; i <= n; i++) {
c[i] = c[i - 1] + a[i] - avg;
}
sort(c + 1, c + n + 1);
LL t = c[(n + 1) / 2], ans = 0;
for (int i = 1; i <= n; i++)
{
ans += abs(t - c[i]);
}
cout << ans;
return 0;
}
P10453 七夕祭
https://www.luogu.com.cn/problem/P10453
读一下发现,行和列处理互不影响
相当于对行和列分别进行均分纸牌
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int N = 1e5 + 10;
int n, m, t, r[N], c[N];
LL d[N], ans, sum, avg;
int main() {
cin >> n >> m >> t;
if (t % n != 0 && t % m != 0) {
cout << "impossible";
return 0;
}
for (int i = 1; i <= t; i++) {
int x, y;
cin >> x >> y;
r[x]++, c[y]++;
}
if (t % n == 0) // 对行进行环形均分纸牌
{
sum = 0, avg = 0;
for (int i = 1; i <= n; i++)
sum += r[i];
avg = sum / n;
for (int i = 1; i <= n; i++)
d[i] = d[i - 1] + avg - r[i];
sort(d + 1, d + n + 1);
for (int i = 1; i <= n; i++)
ans += abs(d[(n + 1) / 2] - d[i]);
}
if (t % m == 0) // 对列进行环形均分纸牌
{
sum = 0, avg = 0;
for (int i = 1; i <= m; i++)
sum += c[i];
avg = sum / m;
for (int i = 1; i <= m; i++)
d[i] = d[i - 1] + avg - c[i];
sort(d + 1, d + m + 1);
for (int i = 1; i <= m; i++)
ans += abs(d[(m + 1) / 2] - d[i]);
}
if (t % m != 0)
cout << "row ";
else if (t % n != 0)
cout << "column ";
else
cout << "both ";
cout << ans;
return 0;
}