C. Squaring
time limit per test: 2 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output
ikrpprpp found an array \(a\) consisting of integers. He likes justice, so he wants to make \(a\) fair — that is, make it non-decreasing. To do that, he can perform an act of justice on an index \(1 \le i \le n\) of the array, which will replace \(a_i\) with \(a_i ^ 2\) (the element at position \(i\) with its square). For example, if \(a = [2,4,3,3,5,3]\) and ikrpprpp chooses to perform an act of justice on \(i = 4\), \(a\) becomes \([2,4,3,9,5,3]\).
What is the minimum number of acts of justice needed to make the array non-decreasing?
ikrpprpp 发现了一个由整数组成的数组 \(a\) 。他喜欢公平,所以想让 \(a\) 变得公平,也就是让它不递减。为此,他可以对数组中的索引 \(1 \le i \le n\) 进行公正操作,将 \(a_i\) 替换为 \(a_i ^ 2\) (位置 \(i\) 的元素及其平方)。例如,如果 \(a = [2,4,3,3,5,3]\) 和ikrpprpp选择在 \(i = 4\) 上执行正义行动,那么 \(a\) 就会变成 \([2,4,3,9,5,3]\) 。
要使数组不递减,最少需要多少次正义行动?
Input
First line contains an integer \(t\) (\(1 \le t \le 1000\)) — the number of test cases. It is followed by the description of test cases.
For each test case, the first line contains an integer \(n\) — size of the array \(a\). The second line contains \(n\) (\(1 \le n \le 2 \cdot 10 ^5\)) integers \(a_1, a_2,\ldots, a_n\) (\(1 \le a_i \le 10 ^ 6\)).
The sum of \(n\) over all test cases does not exceed \(2 \cdot {10}^5\).
输入
第一行包含一个整数 \(t\) ( \(1 \le t \le 1000\) ) - 测试用例的数量。随后是测试用例的描述。
对于每个测试用例,第一行包含一个整数 \(n\) - 数组的大小 \(a\) 。第二行包含 \(n\) ( \(1 \le n \le 2 \cdot 10 ^5\) ) 个整数 \(a_1, a_2,\ldots, a_n\) ( \(1 \le a_i \le 10 ^ 6\) )。
所有测试用例中 \(n\) 的总和不超过 \(2 \cdot {10}^5\) 。
Output
For each testcase, print an integer — minimum number of acts of justice required to make the array \(a\) non-decreasing. If it is impossible to do that, print \(-1\).
输出
对于每个测试用例,打印一个整数--使数组 \(a\) 不递减所需的最小正义行为数。如果无法做到,则打印 \(-1\) 。
Example
input
7
3
1 2 3
2
3 2
3
3 1 5
4
1 1 2 3
3
4 3 2
9
16 2 4 2 256 2 4 2 8
11
10010 10009 10008 10007 10006 10005 10004 10003 10002 10001 10000
output
0
1
-1
0
3
15
55
Note
In the first test case, there's no need to perform acts of justice. The array is fair on its own!
In the third test case, it can be proven that the array cannot become non-decreasing.
In the fifth test case, ikrpprppp can perform an act of justice on index 3, then an act of justice on index 2, and finally yet another act of justice on index 3. After that, \(a\) will become \([4, 9, 16]\).
题意
对每个数可以选择平方或者不平方,可以操作无数次
使得这个数列不递减
我的题解
因为题目给的数据范围很大
如果平方暴力会爆long long
如果开方会丢失精度
所以我们要标记去记录某个数平方了多少次
从第二个数到最后一个数递推(因为第一个数不用动)
首先比较原数字,有两种情况(假设 \(a\) 在 \(b\) 前面)
- \(a \gt b\)
- 那我们就是需要让 \(b\) 不断变成 \(b^2\) 直到 \(b \ge a\) (但是要先把b复制出来,让复制体去平方,不要改变 \(b\) 本身,因为 \(b\) 可能还要和后面的数字比较),记录平方的次数,加上 \(a\) 的平方的次数,就是 \(b\) 真正的平方次数。
- \(a \le b\)
- 虽然理论上我们不需要比较,但是因为 \(a\) 实际上可能已经平方过,我们去算真正的 \(a\) 又可能会爆long long,所以我们不能暴力
- 我们可以计算 \(a\) 需要平方多少次才能实现 \(a \ge b\),然后 \(b\) 实际上需要平方的次数就是 \(a\) 实际上平方的次数减去这个数;如果这个数小于 \(0\),那就只能取 \(0\)。
最后,我们对这些平方次数求和,就是答案了。
我的代码
#include <bits/stdc++.h>
#define int long long
int t,n;
const int N = 2e5 + 1;
int a[N];
int ans[N];
int mem,cnt;
void solve() {
std::cin >> n;
for(int i = 0 ; i < n ; i ++) std::cin >> a[i];
for(int i = 1 ; i < n ; i ++) {
mem = a[i];
cnt = 0;
if(mem < a[i-1]) {
if(mem == 1) {
std::cout << -1 << "\n";
return;
}
while(mem < a[i-1]) {
mem *= mem;
cnt ++;
}
}
else if(a[i-1] != 1){
while(mem >= a[i-1]) {
a[i-1] *= a[i-1];
cnt --;
}
if(a[i-1] != mem) cnt ++;
}
ans[i] = std::max(cnt + ans[i-1],(int)0);
}
int m = 0;
for(int i = 0 ; i < n ; i ++) {
m += ans[i];
}
std::cout << m << "\n";
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
std::cin >> t;
while(t--) solve();
return 0;
}
标签:平方,le,961,int,题解,justice,test,Div,array
From: https://www.cnblogs.com/jiejiejiang2004/p/18324353