Codeforces Round #653 (Div. 3) A、B、C、D、E1题解

目录

比赛链接: Codeforces Round #653 (Div. 3)

1374A. Required Remainder

1374B. Multiply by 2, divide by 6

1374C. Move Brackets

1374D. Zero Remainder Array

1374E1. Reading Books (easy version)


比赛链接: Codeforces Round #653 (Div. 3)

1374A. Required Remainder

题意:给定一个X, Y, N,要求找到一个最大的K(K <= N),使得K % X == Y。

主要代码:

int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		int x, y, n;
		scanf("%d %d %d", &x, &y, &n);
		int c = n % x;
		if(c >= y){
			printf("%d\n", n - (c - y));
		}
		else{
			printf("%d\n", n - (c + x - y));
		}
	}
	return 0;
}

1374B. Multiply by 2, divide by 6

题意:给定一个N,问能不能通过不断地乘2或除6得到1。

思路:如果N%3!=0,则是-1.否则迟早可以得到1。

主要代码:

int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		LL n;
		scanf("%lld", &n);
		int ans = 0;
		bool flag = 1;
		while(n != 1){
			if(n % 3 != 0) {
				flag = 0;
				break;
			}
			if(n % 6 == 0) ans++, n /= 6;
			else ans++, n *= 2;
		}
		if(n == 1) printf("%d\n", ans);
		else printf("-1\n");
	}
	return 0;
}

1374C. Move Brackets

题意:给定一个长度为N的括号序列,保证N为偶数,且左括号与右括号数量相等。问通过几次操作可以使得括号序列是符合括号规则的。操作方法为:选定一个括号将其移至首位或末位。

思路:只要最终的括号序列为:(((())))类似这样的,就必定是规则的,因此只要将不符合括号规则的左括号全提到首位或者不符合括号规则的右括号全移至末位。

主要代码:

int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		int n;
		scanf("%d", &n);
		string s;
		cin >> s;
		int op = 0;
		int ans = 0;
		for(int i = 0; i < n; ++i){
			op += s[i] == '(' ? 1 : -1;
			if(op < 0 && s[i] == ')') ans++, op++;
		}
		printf("%d\n", ans);
	}
	return 0;
}

1374D. Zero Remainder Array

题意:给定一个长度为N的数组A与一个K,有一个隐含的操作数X,X初始为0。每次操作可以有两种选择,一种是选择一个A[i],使得A[i] = A[i] + X, X = X + 1;另一个种是直接X = X + 1。问经过几次操作可以使得数组A中的任意一个元素模K都为0。

思路:将A[i]转化为A[i] % K,可以想到,X实际上也是模K的循环,每次循环如果某一个A[i] + X == K,则此时可以将一个A[i]转化为符合要求的数,那么对于一个A[i],假设A[i]出现的次数为cnt次,则至少需要cnt个循环才能将所有与A[i]相等的数转化成符合要求的数,所以找到出现次数最多的A[i]。那么有可能X不是完整的cnt次循环就可以将所有数转化为满足要求的数。所以要计算出最后一次循环只需要循环几次再加上K*(cnt - 1)次就是答案。

主要代码:

inline bool cmp(int a, int b){return a > b;}
 
int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		int n, k;
		scanf("%d %d", &n, &k);
		vector<int> a(n);
		map<int, int> mp;
		int Max = 0, x = -1;
		bool flag = 0;
		for(int i = 0; i < n; ++i){
			scanf("%d", &a[i]);
			a[i] %= k;
			mp[a[i]]++;
			if(a[i] != 0) flag = 1;
			else continue;
			if(Max < mp[a[i]]){
				Max = mp[a[i]];
				x = k - a[i];
			}
			else if(Max == mp[a[i]]){
				if(x < k - a[i]) x = k - a[i];
			}
		}
		if(flag) printf("%lld\n", k * 1LL * Max - k + x + 1);
		else printf("0\n");
	}
	return 0;
}

1374E1. Reading Books (easy version)

题意:给N本书,阅读第 i 本数需要花费T_i的时间,Alice和Bob有自己喜欢的数,根据输入中的 A_i 和 B_i 确定。给定一个K,问,如果要选出一个书集,书集中Alice喜欢读的有至少K本,Bob喜欢读的也至少有K本,且阅读完这个书集要花费的时间最少。这个最少时间是多少。

思路:如果选择只有Alice喜欢的书中时间最少的书和选择只有Bob喜欢的书中时间最少的书,两者时间相加大于Alice和Bob同时喜欢的书所要花的时间,那么选择共同喜欢的书肯定更优。否则的话就选择前面两本书。若有只有其中一方喜欢的书没得选了,那肯定优先选择共同喜欢的书。

代码:

#define pb push_back

vector<int> t;
vector<int> a, b, ab;
 
bool cmp(int x, int y){return t[x] < t[y];}
inline int cal(int x){
	int ans = ab.size();
	int l = 0, r = ab.size() - 1;
	while(l <= r){
		int mid = l + r >> 1;
		if(t[ab[mid]] <= x) l = mid + 1;
		else r = mid - 1, ans = mid;
	}
	return ans;
}
 
int main(){
	int n, k;
	scanf("%d %d", &n, &k);
	t.resize(n);
	for(int i = 0; i < n; ++i){
		int l, r;
		scanf("%d %d %d", &t[i], &l, &r);
		if(l && !r) a.pb(i);
		if(r && !l) b.pb(i);
		if(l && r) ab.pb(i);
	}
	if(a.size()) sort(a.begin(), a.end(), cmp);
	if(b.size()) sort(b.begin(), b.end(), cmp);
	if(ab.size()) sort(ab.begin(), ab.end(), cmp);
	if(min(b.size() + ab.size(), a.size() + ab.size()) < k) return printf("-1\n"), 0;
	int cura = 0, curb = 0;
	int pre = 0;
	int A, B;
	A = k, B = k;
	int ans = 0;
	while(1){
		if(cura == a.size() || curb == b.size()) break;
		int Mint = t[a[cura]] + t[b[curb]];
		int pos = cal(Mint);
		for(int i = pre; i < pos; ++i){
			A--;
			B--;
			ans += t[ab[i]];
			if(A == 0 || B == 0) break;
		}
		if(A == 0 || B == 0) break;
		ans += t[a[cura]];
		cura++;
		A--;
		ans += t[b[curb]];
		curb++;
		B--;
		if(A == 0 || B == 0) break;
		pre = pos;
	}
	while(A > 0){
		if(pre != ab.size()){
			A--;
			B--;
			ans += t[ab[pre]];
			pre++;
		}
		else ans += t[a[cura]], cura++, A-- ;
	}
	while(B > 0){
		if(pre != ab.size()){
			B--;
			ans += t[ab[pre]];
			pre++;
		}
		else B--, ans += t[b[curb]], curb++;
	}
	printf("%d\n", ans);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值