A. Dense Array
题解:每次乘二即可。
#include<bits/stdc++.h>
using namespace std;
int a[60];
int main()
{
int t, n, i;
scanf("%d", &t);
while (t--){
scanf("%d", &n);
for (i = 1; i <= n; i++)
scanf("%d", &a[i]);
int res = 0;
for (i = 1; i < n; i++){
int mi = min(a[i], a[i + 1]);
int mx = max(a[i], a[i + 1]);
while ((mx + mi - 1) / mi > 2)//向上取整
mi *= 2, res++;
}
printf("%d\n", res);
}
}
B. Balanced Remainders
题解:余数为0,1,2的相互转换。
#include<bits/stdc++.h>
using namespace std;
int a[30010];
int main()
{
int t, n, i;
scanf("%d", &t);
while (t--){
int c0 = 0, c1 = 0, c2 = 0;
scanf("%d", &n);
for (i = 1; i <= n; i++){
scanf("%d", &a[i]);
if (a[i] % 3 == 0) c0++;
else if (a[i] % 3 == 1) c1++;
else c2++;
}
int res = 0;
while (c0 < n / 3){
if (c1 > n / 3){
res += 2;
c1--;
c0++;
}
else{
res++;
c2--;
c0++;
}
}
while (c1 < n / 3){
if (c2 > n / 3){
res += 2;
c2--;
c1++;
}
else{
res++;
c0--;
c1++;
}
}
while (c2 < n / 3){
if (c0 > n / 3){
res += 2;
c0--;
c2++;
}
else{
res++;
c1--;
c2++;
}
}
printf("%d\n", res);
}
}
C. Sum of Cubes
题解:枚举a,二分查找b。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
long long x, i, j;
scanf("%d", &t);
while (t--){
int flag = 0;
scanf("%lld", &x);
for (i = 1; i * i * i < x; i++){
if (flag) break;
long long l = 1, r = 1e4, mid;
while (l <= r){
mid = (l + r) / 2;
if (i * i * i + mid * mid * mid == x){
flag = 1;
break;
}
else if (i * i * i + mid * mid * mid < x) l = mid + 1;
else r = mid - 1;
}
}
if (flag) printf("YES\n");
else printf("NO\n");
}
}
D. Permutation Transformation
题解:建树,以最大值作为根节点,再递归左子树和右子树。
#include<bits/stdc++.h>
using namespace std;
int a[110];
int d[110];
void build(int l, int r, int depth)
{
if (l > r) return;
int mx = 0, id;
for (int i = l; i <= r; i++){
if (a[i] > mx){
mx = a[i];
id = i;
}
}
d[id] = depth;
build(l, id - 1, depth + 1);
build(id + 1, r, depth + 1);
}
int main()
{
int t, n, i;
scanf("%d", &t);
while (t--){
scanf("%d", &n);
for (i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, n, 0);
for (i = 1; i <= n; i++){
if (i > 1) printf(" ");
printf("%d", d[i]);
}
printf("\n");
}
}
E. Accidental Victory
题解:升序处理后,如果前i-1项的和>=第i项,那么第i-1项可以拿;如果小于就不能再拿了,因为前i-1项都小于那么前i-2、i-3项一定小于。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
ll num;
int id;
}a[200010];
bool cmp(node e, node f)
{
return e.num < f.num;
}
ll pre[200010];
int main()
{
int t, n, i;
scanf("%d", &t);
while (t--){
map<int, int>mp;
scanf("%d", &n);
for (i = 1; i <= n; i++){
scanf("%lld", &a[i].num);
a[i].id = i;
}
sort(a + 1, a + 1 + n, cmp);
mp[a[n].id] = 1;
for (i = 1; i <= n; i++)
pre[i] = pre[i - 1] + a[i].num;
int res = 1, p = 0;
for (i = n - 1; i >= 1; i--){
if (pre[i] >= a[i + 1].num){
res++;
mp[a[i].id] = 1;
}
else break;
}
printf("%d\n", res);
for (i = 1; i <= n; i++){
if (mp[i]){
if (p) printf(" ");
printf("%d", i);
p++;
}
}
printf("\n");
}
}
F. Equalize the Array
题意:问最少删几个数使得剩余数的出现次数相同。
题解:枚举出现次数C。如果当前数的出现次数比C小的话,出现次数只能减少不能变多,所以得把这个数删掉;如果和C相同不作处理;如果比C大,那么次数减少到和C相同即可。
#include<bits/stdc++.h>
using namespace std;
int a[200010];
int b[200010];
int suf_b[200010];
int pre[200010];
int suf[200010];
int main()
{
int t, n, i;
scanf("%d", &t);
while (t--){
int mx = 0;
map<int, int>mp1;
map<int, int>mp2;
memset(b, 0, sizeof(b));
memset(pre, 0, sizeof(pre));
memset(suf, 0, sizeof(suf));
memset(suf_b, 0, sizeof(suf_b));
scanf("%d", &n);
for (i = 1; i <= n; i++){
scanf("%d", &a[i]);
mp1[a[i]]++;
mx = max(mx, mp1[a[i]]);//Cmax
}
for (i = 1; i <= n; i++){
if (!mp2[a[i]]){//mp2判断a[i]有无用过
b[mp1[a[i]]]++;//统计某一次数的种类数
mp2[a[i]] = 1;
}
}
for (i = 1; i <= n; i++) pre[i] = pre[i - 1] + b[i] * i;//前i次的数字个数
for (i = n; i >= 1; i--) suf[i] = suf[i + 1] + b[i] * i;//后i次的数字个数
for (i = n; i >= 1; i--) suf_b[i] = suf_b[i + 1] + b[i];//后i次的种类数
int mi = 1e9 + 10;
for (i = 1; i <= mx; i++)
mi = min(mi, pre[i - 1] + suf[i + 1] - suf_b[i + 1] * i);//出现i-1次以下的直接删掉,出现i次的不作处理,出现i+1次以上的减到i次为止
printf("%d\n", mi);
}
}