CF Round #631 题解

\(Codeforces\) \(Round\) \(631\)

A.Dreamoon and Ranking Collection

题目大意:

\(n\)轮比赛,每轮比赛排名已经给出,还可以进行额外的\(m\)场比赛

问:所有比赛进行完后,最多可以收集到从\(1\)开始的多少个连续名次

题解:

用一个数组统计一下排名的出现情况,然后扫一遍添加\(m\)个缺失名次即可

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int main(){
	int i,j,k,n,a,x,t,s[105],ans,mmax;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&x);
		memset(s,0,sizeof(s));
		ans=0;mmax=0;
		for(i=1;i<=n;i++){scanf("%d",&a);s[a]=1;mmax=max(mmax,a);}
		for(i=1;i<=mmax;i++){
			if(s[i]){ans=i;continue;}
			else if(s[i]==0&&x){x--;s[i]=1;ans=i;}
			else if(s[i]==0&&x==0){ans=i;break;}
		}
		while(s[ans]==1)ans++;
		ans+=x;
		ans--;
		printf("%d\n",ans);
	}
	return 0;
}

B. Dreamoon Likes Permutations

题目大意:

给出\(n\)和长度为\(n\)的一个数列,可将其分为左右两部分,问有多少种分法,使得左右两部分都为从\(1\)开始的一个排列。输出方案数以及全部方案。

题解:

从左往右和从右往左各扫一次,处理出数组\(l_1\)、\(l_2\),分别表示从第\(1\)位和第\(n\)位到第\(i\)位的所有数是否构成一个排列。然后枚举断点,如果左右两侧都是一个排列,那么当前断点就是一个方案,输出即可。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int t,n,a[200005],mmax,s1[200005],s2[200005],l1[200005],l2[200005];
void doit(){
	int i,j;
	mmax=0;
	for(i=1;i<=n;i++){
		mmax=max(mmax,a[i]);
		s1[a[i]]++;
		if(s1[a[i]]==1&&mmax==i)l1[i]=1;
		else if(s1[a[i]]>=2)break;
	}
	mmax=0;
	for(i=n;i>=1;i--){
		mmax=max(mmax,a[i]);
		s2[a[i]]++;
		if(s2[a[i]]==1&&mmax==n-i+1)l2[i]=1;
		else if(s2[a[i]]>=2)break;
	}
}
int main(){
	int i,j;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		memset(s1,0,sizeof(s1));
		memset(s2,0,sizeof(s2));
		memset(l1,0,sizeof(l1));
		memset(l2,0,sizeof(l2));
		for(i=1;i<=n;i++){scanf("%d",&a[i]);}
		doit();
		int ans=0;
		for(i=1;i<n;i++)
			if(l1[i]&&l2[i+1])ans++;
		if(ans==0)printf("%d\n",ans);
		else{
			printf("%d\n",ans);
			for(i=1;i<n;i++)
				if(l1[i]&&l2[i+1])
					printf("%d %d\n",i,n-i);
		}
	}
	return 0;
}

C. Dreamoon Likes Coloring

题目大意:

\(n\)个格子,\(m\)次染色次数,每次染色宽度为\(l_i\),颜色为\(i\)

后染的颜色会覆盖原来的颜色

求一种染色方案使得每个格子都有颜色并且最后每个颜色都要出现

若无方案则输出\(-1\)

题解:

1.每个颜色至少要占一个格子,那么在第\(i\)个颜色涂上去之前,必定有\(i-1\)个格子已经有颜色了,因此\(n-li<i-1\)时必定无解。

2.总长度\(<n\)时必定无解。

3.其他情况均为有解情况,为获得方案,只需先默认第i个颜色从第i个格子开始涂。然后再贪心的将部分颜色往后面挪以填充未染色的格子即可。

ps.代码中是从后往前图的颜色

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long lol;
lol n,m,l[100005],sum,ans[100005];
int main(){
	lol i,j;
	scanf("%lld%lld",&n,&m);
	for(i=1;i<=m;i++){scanf("%lld",&l[i]);sum+=l[i];}
	for(i=1;i<=m;i++)
		if(n-l[i]<i-1){
			printf("-1\n");
			return 0;
		}
	if(sum<n){
		printf("-1\n");
		return 0;
	}
	lol len=m+l[m]-1,need=n-len,place=n-l[m]+1;
	for(i=m;i>=1;i--){
		ans[i]=place;
		if(need==0)place--;
		else{
			place-=min(l[i-1]-1,need)+1;
			need-=l[i-1]-1;
			if(need<0)need=0;
		}
	}
	for(i=1;i<=m;i++)
		printf("%d ",ans[i]);
	printf("\n");
	return 0;
}

D. Dreamoon Likes Sequences

题目大意:

对于每组数据给出两个整数\(d\)和\(m\)

求满足下列条件的数列\(a_n\)的个数对\(m\)取模的结果

1.\(1≤a_1<a_2<?<a_n≤d\)

2.\(a_n\)的前缀异或和\(b_n\)也为单调递增数列

题解:

由异或运算得到本题应从二进制角度来思考。

由异或和单调递增可知,数列\(a_n\)的最高位单调递增。

于是讨论二进制最高位的位数:

1.位数为\(1\)时,有\(1\)种

2.位数为\(2\)时,有\(2\)种

3.位数为\(3\)时,有\(4\)种

...(以此类推)

故答案为\(ans=(1+1)*(2+1)*(4+1)...-1\)

ps.\(+1\)是因为当前数可以不取,\(-1\)是因为要减去全部都不取的情况。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long lol;
lol n,mod,t;
int main(){
	scanf("%lld",&t);
	while(t--){
		scanf("%lld%lld",&n,&mod);
		lol ans=1%mod,x=1;
		while(x<=n){
			ans=(ans*(min(x,n-x+1)+1))%mod;
			x<<=1;
		}
		ans--;
		ans%=mod;
		while(ans<0)ans+=mod;
		printf("%lld\n",ans);
	}
	return 0;
}

E. Drazil Likes Heap

题目大意:

给定一个层数为\(h\)的满二叉大根堆,再给定一个整数\(g\)。

每次操作删除堆中的一个数。

求一个删除堆中元素的方案,使得:

1.最后得到的堆为一个\(g\)层的满二叉大根堆。

2.该堆的元素和最小。

输出最小的和以及删除方案。

题解:

不难得到以下结论:

1.每次删除一个节点,由它大儿子和大孙子组成的链的深度\(-1\)。

2.一个节点不可删,当且仅当它大儿子和大孙子等组成的链的深度等于\(g\)。

3.一个节点不可删,那么它的大儿子也不可删。由它大儿子和大孙子组成的链都不能删。

于是得到贪心算法,如果根节点能删则删,否则把左右儿子当作根分别进行删除操作。

这样能够保证随后得到的堆的元素和是最小的。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll(x) (x<<1)
#define rr(x) (x<<1|1)
using namespace std;
typedef long long lol;
int n,m,t,h,g,cnt,a[2500000],ans[2500000];
lol sum;
void del(int x){
	if(a[ll(x)]==0&&a[rr(x)]==0)a[x]=0;
	else{
		if(a[ll(x)]>a[rr(x)]){
			a[x]=a[ll(x)];
			del(ll(x));
		}
		else{
			a[x]=a[rr(x)];
			del(rr(x));
		}
	}
}
int get_depth(int x,int depth){
	if(a[x]==0)return depth-1;
	if(a[ll(x)]>a[rr(x)])return get_depth(ll(x),depth+1);
	else return get_depth(rr(x),depth+1);
}
void dfs(int x,int depth){
	if(a[x]==0)return;
	while(get_depth(x,depth)>m){del(x);ans[++cnt]=x;}
	dfs(ll(x),depth+1);
	dfs(rr(x),depth+1);
}
int main(){
	int i;
	scanf("%d",&t);
	while(t--){
		cnt=0;sum=0;
		scanf("%d%d",&n,&m);
		h=(1<<n)-1;g=(1<<m)-1;
		for(i=1;i<=h*2+1;i++)a[i]=0;
		for(i=1;i<=h;i++)scanf("%d",&a[i]);
		dfs(1,1);
		for(i=1;i<=g;i++)sum+=a[i];
		printf("%lld\n",sum);
		for(i=1;i<=cnt;i++)
			printf("%d ",ans[i]);
		printf("\n");
	}
	return 0;
}

BBT

没啥,就是觉得自己菜的一批

原文地址:https://www.cnblogs.com/huangdalaofighting/p/12637116.html

时间: 2024-11-10 14:34:52

CF Round #631 题解的相关文章

CFEducational Codeforces Round 66题解报告

CFEducational Codeforces Round 66题解报告 感觉丧失了唯一一次能在CF上超过wqy的机会QAQ A 不管 B 不能直接累计乘法打\(tag\),要直接跳 C 考虑二分第\(k\)小的值 那么问题就变成了 每一个数变成了\([x-mid,x+mid]\)的一段区间,如果有一个位置被覆盖了超过\(k\)次 那么\(mid\)一定合法 类似括号匹配 每次碰到左端点就贡献+1 右端点就统计答案然后-1 维护答案的同时顺便维护位置就好了 #include<cstdio>

CF Round 594

CF Round 594(Div1) (A~D)简要题解 开学基本打不了cf了啊.. A Ivan the Fool and the Probability Theory 对于 $ 1 \times n $ 的情况,稍微推一推式子发现是斐波那契数列的两倍(因为第一个位置可以是0可以是1,就是两倍了,否则是一倍). 考虑第一行,第一行有两种情况: 如果第一行是 01010... 交错的,那么 0 开头可以看成一种颜色,1 开头可以看成一种颜色.然后就成了一个竖着的 $ 1 \times n $ 的

Codeforces Round #541 题解

codeforces Round #541 C 题意 给你100个人,让你将它们围成一个圆,使得:"任意相邻的两人身高差的绝对值" 中的最大值 最小 题解 显然的构造方法:先排序,让所有人1 2 报数,报2的出列,排尾变排头接到报 1 的原队列后面 证明: 显然这样的构造方法保证身高差最大为 max{(a[i+2]-a[i]) }(i=1..n,环状,a[i]升序): 我们可以说明对于任意的i,身高差至少为(a[i+2]-a[i]), 如果我们将每个人看成一个点,相邻关系看成一条无向边

CF Round #629

CF Round #629 A.数学 给定a,b,现在问你最小让a加多少使得a能被b整除,可以为0 即算(b-(a%b))%b B.数学 给定n和k 问以n-2个a和2个b组成的串中,以字典序升序排列,问第k个是几 这个有点类似康托展开,这个简化了很多 首先考虑第一个b,它处在从左往右数第p位,那么无论第二个b怎么放,它最大是(p-1)*p/2 所以只要找到第一个b为u,第二个b从u-1开始,每往后移一位就小一,找k即可 C.数学 给定n和x x是一串开头必为2,由0,1,2组成的字符串,一共有

【codeforces】【比赛题解】#915 Educational CF Round 36

虽然最近打了很多场CF,也涨了很多分,但是好久没写CF的题解了. 前几次刚刚紫名的CF,太伤感情了,一下子就掉下来了,不懂你们Div.1. 珂学的那场我只做了第一题--悲伤. 这次的Educational Round打的还可以,虽然吧没有涨分(因为我是紫色的啊). 做了前4题,后面3题也比较简单,陆续也做完了. 所以心情好,来写一篇题解! [A]花园 题意: 长度为\(k\)的线段,用若干个长度为\(a_i\)的线段,正好覆盖.(\(a_i|k\)) 给定\(n\)个\(a_i\),求出最小的\

【codeforces】【比赛题解】#854 CF Round #433 (Div.2)

cf一如既往挺丧 看丧题点我! [A]分数 Petya是数学迷,特别是有关于分数的数学.最近他学了所谓一个分数被叫做"真分数"当且仅当其分子小于分母,而一个分数被叫做"最简分数"当且仅当其分子分母互质.在闲暇时间,Petya在用计算器研究:如何把最简真分数转换为小数等问题.有一天他不小心把除号(÷)按成了加号(+),导致他得到了分子与分母的和.Petya想要得到他原来的分数,但他很快发现这不是唯一的.所以现在他想要知道最大的最简真分数使得其分子与分母的和为n. 输入

【codeforces】【比赛题解】#849 CF Round #431 (Div.2)

cf的比赛越来越有难度了--至少我做起来是这样. 先看看题目吧:点我. 这次比赛是北京时间21:35开始的,算是比较良心. [A]奇数与结束 "奇数从哪里开始,又在哪里结束?梦想从何处起航,它们又是否会破灭呢?" 给定一个长度为n的序列.确定能不能将序列分成奇数个长度为奇数的非空字串,而且这其中每个子串以奇数开头,以奇数结尾.可以只分成一个(1也是奇数). 输入 第一行一个正整数n,表示序列长度. 第二行n个整数,表示序列中的元素. 输出 输出"Yes"或"

Codeforces Round #631 (Div. 2) C. Dreamoon Likes Coloring(贪心好题/意识流题解)

Dreamoon likes coloring cells very much. There is a row of nn cells. Initially, all cells are empty (don't contain any color). Cells are numbered from 11 to nn . You are given an integer mm and mm integers l1,l2,…,lml1,l2,…,lm (1≤li≤n1≤li≤n ) Dreamoo

“玲珑杯”ACM比赛 Round #19题解&amp;源码【A,规律,B,二分,C,牛顿迭代法,D,平衡树,E,概率dp】

A -- simple math problem Time Limit:2s Memory Limit:128MByte Submissions:1599Solved:270 SAMPLE INPUT 5 20 1314 SAMPLE OUTPUT 5 21 1317 SOLUTION “玲珑杯”ACM比赛 Round #19 题目链接:http://www.ifrog.cc/acm/problem/1145 分析: 这个题解是官方写法,官方代码如下: 1 #include <iostream>