A. Dense Array
遍历一遍,求最大值时最小值的2的几次幂倍
#include<bits/stdc++.h>
using namespace std;
int t, n;
int a[52];
int sum;
int main(){
cin >> t;
while(t--){
cin >> n;
sum = 0;
for(int i=1; i<=n; ++i)
cin >> a[i];
for(int i=1; i<=n-1; ++i){
int x, y;
x = max(a[i], a[i+1]);
y = min(a[i], a[i+1]);
int j;
int c=1;
for(j=1; j<=10; ++j){
c*=2;
if(y*c >= x) break;
}
sum += j-1;
}
cout << sum << endl;
}
}
B. Balanced Remainders
每次对一个数进行加1操作,可以看作它的余数改变了,0,1,2可以看作一个约瑟夫环。余数0,1,2的个数用数组c[]存,假设余数为x,对数的加1操作可以看作c[x]-1;c[(x+1)%3]+1;遍历c中的元素,将大于平均值的元素多出的值转移到下一个元素,循环直到数组中的元素相等
#include<bits/stdc++.h>
using namespace std;
const int N=3e4+4;
typedef long long ll;
int t, a[N];
ll n, c[3];
int main(){
cin >> t;
while(t--){
cin >> n;
memset(c, 0, sizeof(c));
for(int i=1; i<=n; ++i){
cin >> a[i];
if(a[i]%3 == 0) c[0]++;
else if(a[i]%3 == 1) c[1]++;
else c[2]++;
}
int ave = (c[0]+c[1]+c[2])/3;
int num=0;
while(c[0] != ave || c[1] != ave || c[2] != ave){
for(int i=0; i<=2; ++i){
if(c[i] > ave){
c[(i+1)%3] += c[i]-ave;
num += c[i]-ave;
c[i]=ave;
}
}
}
cout << num<< endl;
}
}
C. Sum of Cubes
第一个数范围1到 x 1 3 x^\frac{1}{3} x31,遍历第一个数,第二个数二分查找
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
ll x;
int main(){
cin >> t;
while(t--){
cin >> x;
ll lim = pow(x, 1.0/3);
bool f=0;
for(int i=1; i<=lim; ++i){
ll left=1, right=floor(lim), mid;
while(left <= right){
mid = (left+right)/2;
ll tmp = pow(i, 3)+pow(mid, 3);
if(x > tmp) left = mid+1;
else if(x < tmp) right=mid-1;
else {
f=1; break;
}
}
}
if(f==1) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
D. Permutation Transformation
dfs,每次存下当前的深度就行
#include<bits/stdc++.h>
using namespace std;
int t, n;
int a[102], d[102];
void dfs(int lef, int rig, int hei){
if(lef>rig) return;
int maxx=0, idx=0;
for(int i=lef; i<=rig; ++i){
if(a[i] > maxx){
maxx = a[i];
idx = i;
}
}
d[idx] = hei;
dfs(lef, idx-1, hei+1);
dfs(idx+1, rig, hei+1);
}
int main(){
cin >> t;
while(t--){
cin >> n;
memset(d, 0, sizeof(d));
for(int i=1; i<=n; ++i)
cin >> a[i];
dfs(1, n, 0);
for(int i=1; i<=n; ++i)
cout << d[i] << ' ';
cout << endl;
}
}
E. Accidental Victory
sort一下,算下前辍和就出来了
已知一个人可以把小于等于他代币的人全打败,从后往前遍历,如果当前人的前辍和(不是所有比他代币小或等于的人的代币总和加上自己的代币,是排序后下标在他前面的代币总和加上自己的代币)大于等于后一个人的代币,他就可能获得冠军。
如果从前往后升序遍历,只能确定当前人能否打败后一个人,无法确定他是否能成为冠军。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n, id[N];
ll sum[N];
struct node {
int x;
int idx;
};
bool cmp(node a, node b){
return a.x < b.x;
}
int t;
int main(){
cin >> t;
node a[N];
while(t--){
cin >> n;
int i;
memset(sum, 0, sizeof(sum));
memset(id, 0, sizeof(id));
for(i=1; i<=n; ++i){
cin >> a[i].x;
a[i].idx = i;
}
sort(a+1, a+n+1, cmp);
for(i=1; i<=n; ++i){
sum[i] += sum[i-1]+a[i].x;
}
for(i=n; i>=1; --i){
if(i == n) id[i]=a[i].idx;
else if(i==1 && a[1].x==a[2].x) id[i]=a[i].idx;
else if(sum[i] >= a[i+1].x) id[i]=a[i].idx;
else break;
}
sort(id+1, id+1+n);
cout << n-i << endl;
for(int i=1; i<=n; ++i){
if(id[i] != 0) cout << id[i] << ' ';
}
cout << endl;
}
}
F. Equalize the Array
看网上的代码才懂
大概意思就是将每个不同数的数量存一下,sort一下,数的总数为n,设数量比c大或等于的数个数为m(不同的数),操作数需要n-
m
∗
c
m*c
m∗c,求出
m
∗
c
m*c
m∗c 的最大值即可。
#include<bits/stdc++.h>
using namespace std;
int t, n, x;
const int N=2e5+5;
map <int,int> mp;
int arr[N];
int main(){
cin >> t;
while(t--){
cin >> n;
mp.clear();
int cnt=0;
for(int i=1; i<=n; ++i){
cin >> x;
if(!mp[x]) arr[++cnt]=x;
++mp[x];
}
for(int i=1; i<=cnt; ++i){//离散化
arr[i]=mp[arr[i]];
}
sort(arr+1,arr+cnt+1);
int maxn=0;
for(int i=1; i<=cnt; ++i){
maxn=max(maxn,(cnt-i+1)*arr[i]);
}
cout << n-maxn << endl;
}
}
G. Old Floppy Drive
看网上的代码才懂了一点点
用b[]数组存递增的前辍和(如果比前面一个小不存入b数组),id[]存在a[]对应的位置
如果x>b[tot](最大的前辍和)且sum(圆盘一轮走完的值)<=0
则不可能达到x
如果走一圈就能达到x,对b[]二分查找到第一个大于或等于x的元素的下标
如果x>b[tot]且sum>0,cnt为要走的圆圈数,设step为走完与圆圈后还需走的步数。所需时间为
c
n
t
∗
n
cnt*n
cnt∗n+step; x=
c
n
t
∗
s
u
m
cnt*sum
cnt∗sum+b[step+1],如果所花步数要最小,cnt要最小(向上取整),所以取最大值b[tot]算出最小所需cnt,再二分。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int a[N];
ll id[N], b[N];
int main(){
int t, n, m, x;
cin >> t;
while(t--){
ll sum=0, tot=0;
memset(b, 0, sizeof(b));
cin >> n >> m;
for(int i=1; i<=n; ++i){
cin >> a[i];
sum += a[i];
if(sum > b[tot]) b[++tot] = sum, id[tot] = i;
}
for(int i=1; i<=m; ++i){
cin >> x;
if(i>1) cout << ' ';
if(x > b[tot] && sum <= 0){
cout << "-1";
continue;
}
if(x <= a[1]){
cout << "0";
continue;
}
if(x <= b[tot]){
ll it = lower_bound(b+1, b+tot+1, x)-b;
cout << id[it]-1;
}
else{
ll cnt = ceil((x-b[tot])*1.0/sum);
ll it = lower_bound(b+1, b+tot+1, x-cnt*sum)-b;
cout << n*cnt+id[it]-1;
}
}
cout << endl;
}
}