Codeforces Round #706 (Div. 2) 3月10号 A-C题

前言 希望自己以后每次打完cf 都能写一篇博客总结一下 才能有提升
这一场爆0了 难受啊 感觉自己太菜了 还是要多练练啊 以后的cf每次都要参加

A. Split it!

题目大意 :就是给你一个字符串和一个数k 然后让你观察这个字符串是否存在k+1个非空字符串a1,a2…,ak+1
s=a1+a2+…+ak+ak+1+R(ak)+R(ak−1)+…+R(a1)。
这里+表示串联。我们将R(x)定义为反向字符串x。例如R(abcd)=dcba (来自百度翻译)

其实就是让你观察这是否是一个回文字符串 有一个中间字符串 不用找翻转的 就相当于这个ak+1的字符串为这个大字符串的中心 然后你可以把它看成是一个点 然后在往两边找回文字母的个数 当k等于0时一定输出YES 然后当这个字母个数会大于等于k时 输出YES 否则输出NO 就行了

一开始写的时候一直显示Wrong answer on test 2 人都快傻了 结束了都不知道为啥 后面看了一眼题解才知道 我理解的有点问题 对于这个中间的不用回文的字符串 找错了 我计算的时候一直以为 这个大字符串一定要满足回文的状态 否则直接输出NO
结果一直没发现它是错的

正确代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxt=110;
int t,n,k;
char h[maxt];
int main()
{
	cin>>t;
	while(t --){
		cin>>n>>k;
		cin>>h;
		if(k==0) cout<<"YES"<<endl;
		else {
			int r=0;//中间的字符串是独立的不受影响 一旦不满足回文的时候直接退出循环就可以了 
			for(int i=0,j=n-1;j-i>1;i ++,j--){//在这里的判断条件设为j-i>1的时候很妙 就不用考虑字符串个数是奇数还是偶数了
				if(h[i]==h[j]) r++;
				else break;
			}
			if(r>=k) cout<<"YES"<<endl;
			else cout<<"NO"<<endl;
		}
		
	}
return 0;	
 } 

B. Max and Mex

题目大意:给你S集合(非负数)中有n个数进行k次操作 每次从中得出两个数a=mex(S) b=max(S),mex(S)的意思就是在这个集合中没有出现过的最小数,max(S)的意思是这集合中最大的数
然后x=((a+b)/2) 将这个数加入到S集合中 最后再求这个集合中有多少个不同的元素。

题目意思还是蛮好理解的 就是不知道为啥我码的代码超时了 感觉是自己的思路有点问题
正确思路 :
可以分成三种情况
1.当k=0时 不用做操作 有n个不同元素
2.当k不等于0时 集合S中是0到n的全排列 最后是有k+n个不同元素
3.当k既不等于0也不是全排列时 找到x值判断这个值是否在这个集合中出现过 如果出现过 不管k是多少 最后都是有n个不同的元素 如果没有出现过 就是有n+1个不同的元素

思路理清了 还是挺简单的
正确代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxt = 100010;
int t, n, k;
int h[maxt];
int main()
{
	cin >> t;
	while (t--) {
		cin >> n >> k;
		for (int i = 0; i < n; i++) {
			cin >> h[i];
		}
		sort(h, h + n);
		int sum;
		if (k == 0) sum = n;
		else {
			int x, y, res = 1;
			for (int i = 0; i < n; i++) {
				if (h[i] != i) {
					x = i;
					res = 0;
					break;
				}
			}
			if (res) sum = n + k;
			else {
				y = h[n - 1];
				int a = (x + y) / 2;
				if ((x + y) % 2 == 1) a++;
				for (int i = 0; i < n; i++) {
					if (a == h[i]) {
						sum = n;
						res = 1;
						break;
					}
				}
				if (res == 0) sum = n + 1;

			}
		}
		cout << sum << endl;

	}
	return 0;
}

C. Diamond Miner

题目大意:题目意思还是很好理解的 这里就不多赘述了(其实是因为懒 “手打狗头”)
其实一开始如果不知道怎么写的话 可以用几个样例试一下就出来了 比如第2个样例 就很好
试了一下就会发现 当把每个离原点最近的点对应连起来这样的总距离是最小的 然后直接输出就行了
在这里要注意一个地方 输入要用scanf() 不然会出问题 别问为什么 问就是又在这里翻车了
以后再也不偷懒用cin了

#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxt = 100010;
int t, n;
double h[maxt], k[maxt];
double sum = 0;
int main()
{
	cin >> t;
	while (t--) {
		cin >> n;
		sum = 0;
		int a=0,b=0;
		double x,y;
		for (int i = 1; i <= n * 2; i++) {
			scanf("%lf %lf",&x,&y);
			if (x == 0) h[a++] = y * y;
			else k[b++] = x * x;
		}
		sort(h, h + n);
		sort(k, k + n);
		for (int i = 0; i < n; i++) {
			sum += sqrt(h[i] + k[i]);
		}
		printf("%.15lf\n", sum);//这里其实保留10位小数就可以 题目要求了 误差不超过10的-9次方就可以 
	}
	return 0;
}

希望自己以后可以坚持下去
能力有限 先以三题为目标 以后如果能力允许的话希望可以多写几题
一起共勉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值