2021-02-20 Codeforces Round #702 (Div. 3)

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 mc,求出 m ∗ c m*c mc 的最大值即可。

#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 cntn+step; x= c n t ∗ s u m cnt*sum cntsum+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;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值