Codeforces Round #493 比赛总结

总述

作为一个新手,这是本人第一次认真打cf(上次打的时候电脑没电关机了,这次电脑居然蓝屏了一次,实在是伤不起呀),感触也颇多,这里进行一个总结吧。比赛链接http://codeforces.com/contest/998

998A.  Balloons

是一道大水题,只要根据n是1,是2或大于2分类讨论,大于2时输出最小数。可是当时想多了,题目理解错了,WA了3次,到最后才发现真相,只得了150分。以后还是要提高姿势水平呀,提高思考速度与手速。

#include<bits/stdc++.h>
#define REP(i,n) for(int i=0;i<n;++i)
using namespace std;
int a[15];
int main()
{
	int n;scanf("%d",&n);
	REP(i,n) scanf("%d",a+i);
	if(n<2) puts("-1");
	else if(n==2) {if(a[0]==a[1]) puts("-1");else puts("1\n1");}
	else{puts("1");int minn=0;
		REP(i,n) minn=(a[i]<a[minn])?i:minn;
		printf("%d\n",minn+1);
	}
	return 0;
}

998B. Cutting

水题,找到可以开刀的地方,存储开刀花费,排序后贪心即可。

#include<bits/stdc++.h>
#define REP(i,n) for(int i=0;i<n;++i)
#define ms0(s) memset(s,0,sizeof(s))
#define abs(x) (((x)>0)?(x):-(x))
using namespace std;
int a[105],ok;
int cuts[105],cnt;
int main()
{
	int n,b;scanf("%d%d",&n,&b);ok=0;cnt=0;
	REP(i,n) {
		scanf("%d",a+i);
		ok+=(a[i]&1)?1:-1;
		if(ok==0&&i!=n-1) cuts[cnt++]=i;
	}
	REP(i,cnt) 
		cuts[i]=abs(a[cuts[i]]-a[cuts[i]+1]);
	sort(cuts,cuts+cnt);int cost=0;int i;
	for( i=0;cost<b&&i<n;i++)cost+=cuts[i];if(cost>b)i--;
	printf("%d\n",i);
	return 0;
}


998C. Convert to Ones

这道题需要稍微想一想,我们应当数一数整个串中有多少个互相分离的0部分(如001101有2个0部分),为了使效率最优,两种操作最优方案如下:反转操作把两个0部分合为一体,使得0部分数量减少1;取反操作把一个0部分全部变为1,即消灭一个0部分。一次操作都能使0部分减少1,由此,把原有的k个0部分全部消灭需要进行k次操作。至少要1次取反,至多要k次。根据条件给出的价格,总开支是关于取反次数的线性函数,如果取反价格高,那就反转k-1次,取反1次;如果反转价格高,那就取反k次。

#include<bits/stdc++.h>
#define REP(i,n) for(int i=0;i<n;++i)
#define ms0(s) memset(s,0,sizeof(s))
using namespace std;
typedef long long ll;
int zero[300005],cnt;ll cost;
int main()
{
	int n,x,y;bitset<300005> b;
	scanf("%d%d%d",&n,&x,&y);cnt=0;
	bool one=1;
	REP(i,n){
		b[i]=(getchar()=='1');
		if(b[i]==0){if(one)cnt++,one=0;zero[cnt]++;}
		else one=1;
	}
	if(!cnt&&one) {puts("0");return 0;}
	cost=(ll)0;
	if(y<=x) cost=(ll)y*(ll)(cnt);
	else cost=(ll)y+(ll)x*(ll)(cnt-1);
	printf("%I64d\n",cost);
	return 0;
}

998D. Roman Digits

这是一道数学题,当时看了之后感觉要凑等效表达方式,但没凑出来,就没做出来。第二天仔细思考后发现,由于长度固定,实际上把{1,5,10,50}可以完全等效为{0,4,9,49},这一步让拼凑大大简化。可以证明,只要在一个数的表示中找不到4和9的个数为(0,9),(9,0),(1,5)的组,这个表示就是唯一的。(注:第一个可以将9个4换成4个9与5个0,第二个可以将9个9换成1个49与8个4,第三个可以把1个4,5个9换为1个49与5个0,这样我们就找到了同一个数的不同表达方式)因此我们枚举剩下的组合,根据4和9用掉的数位个数分类相加,最后得到49n-247的表达式。但是对于n<12,有一些长度是达不到的,如n为4时就无法出现9个4的情况,要把这些多减去的情况加上,最后按n与12的大小关系分类讨论进行输出。(事实上直接打表找规律也是可以的,可惜当时没想到)代码非常简洁:

#include<bits/stdc++.h>
int a[]={0,4,10,20,35,56,83,116,155,198,244,292};
using namespace std;
typedef long long ll;
int main()
{
	int n;scanf("%d",&n);
	if(n<=11) printf("%d\n",a[n]);
	else printf("%I64d\n",(ll)49*(ll)n-(ll)247);
	return 0;
}

998E. Sky Full of Stars

这是一道较为困难的组合数学题,用容斥原理做,详情参照官方题解。

总结

这次比赛结果rank1300+,rating+=24。

总的来说要改进的是以下几个方面吧:

1. 问题想清楚了再编程,不要心急,像第一题WA3次就是没想清楚的体现

2.提高编码速度,提高调适能力。做了3道题的人最高排名是400左右,可是我罚时太高了,只排到1300.

3.后半场冷静思考,注意找规律。像D题如果仔细想是可以做出来的,即使打表找规律也是有时间的,可惜当时有些怠惰了。


UPD:增加了题目代码

猜你喜欢

转载自blog.csdn.net/qq_41255467/article/details/80882752