Codeforces Round #854 by cybercats (Div. 1 + Div. 2) B. Equalize by Divide【暴力、模拟】

链接
传送门
分析
这道B题还是有点点难度的,不算很简单。首先如果说每个数都相同的话就不用操作了。如果需要操作,那么什么时候不行呢?如果说里面有一个1就无法操作了,因为什么数除1都不会改变,1被除的就会变成零,最后一个总有一个值不是零。那么如果说没有1呢?那么我们首先找到最小值,让后遍历这个数组,如果说这个数比这个数大除完之后一定大于等于2,如果说除完之后比minn要小了,更新minn,使得minn永远是数组中的最小值,因为大数除小数并且向上取整,必定大于等2,不会出现1,每次必定减小,所以不会出现死循环。因为减少量的贡献是至少是除2,减少量至少是2,但是增加量贡献最多是1。例如,5 / 2 = 2.5 = 3,整数部分5 整除 2 等于2减少了3,如果还有小数部分+1,记作a / b = c, 前者写成 k b + r 整除 b ->k, r / b 向上取整,对于前者的减少贡献量是(b - 1) * k,b>=2,k>= 2,所以减少量大于等于2,完毕。
实现

#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N = 105, p = 1e9 + 7;
typedef pair<int, int> PII;
int a[N];
int n;
bool check() {
	for (int i = 1; i <= n; i++) {
		if (a[i] != a[1]) return 1;
	}
	return 0;
}
void solve() {
	cin >> n;
	int minn = inf, p;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		if (a[i] < minn) {
			minn = a[i];
			p = i;
		}
	}
	if (!check()) {
		cout << 0 << '\n';
		return;
	}
	if (minn == 1) {
		cout << -1 << '\n';
		return;
	}
	vector<PII> ans;
	while (check()) {
		for (int i = 1; i <= n; i++) {
			while (a[i] > minn) a[i] = (a[i] + minn - 1) / minn, ans.push_back({i, p});//这里是向上取整的一种写法
			if (a[i] < minn) minn = a[i], p = i;
		}
	}
	cout << ans.size() << '\n';
	for (auto x : ans) {
		cout << x.first << ' ' << x.second << '\n';
	}
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T = 1;
	cin >> T;
	while (T--) solve(); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值