题目链接
题目大意
有一个长度为 n 的数组
做操作使这个数组不递减:
- 把一个数分成两个数,例如:x 分为 a 和 b, x == a + b
求最小操作次数
思路
见注释
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 10;
int a[N];signed main()
{int T;cin >> T;while (T -- ){int n; cin >> n;for (int i = 1; i <= n; i ++ ) cin >> a[i];int ans = 0;for (int i = n - 1; i >= 1; i -- ) {if (a[i] > a[i + 1]){int x = a[i] / a[i + 1]; //分成几个数 if (a[i] % a[i + 1] != 0) x ++; //如果有余数,那就多分出了一个数a[i] = a[i] / x; //使分成的那几个数的最小值尽可能大,就取一下平均值// 例如//a[i] = 13, a[i + 1] = 3//直接除后的方法使我们知道需要分成5个数字://1, 3, 3, 3, 3//但是1太小了,会影响a[i - 1] //要使它变大,就让13 / 5, 取平均值//得到 2, 2, 2, 2, 2, 余3,多的3就放在最后三位//即 2, 2, 3, 3, 3,//因为相当于是把多的往少的匀,所以绝对不会影响到a[i + 1] ,即最大值不会超过a[i + 1] ans += (x - 1);// x是分成的数的个数,x - 1就是需要的步骤数}}cout << ans << endl; }return 0;
}
总结
复述一遍思路:
当前面的数比后面的数大时,就需要拆分这个数,拆成尽可能少的个数,每个数还要尽可能大,这些数取决于后一个数,当前数 除以后一个数,如果能整除,那就分为那么多个数,且是最大的,若不能,则会多分出一个数,要使它们尽可能大(最小值最大),就是要让那个余数最大,但余数肯定大不过除数,就把这个数平均分为这么多个数,多出来的就平均分配进分出来的每一个数里面,实现最大化最小值的操作。