2022牛客多校联赛第五场 题解

比赛传送门

签到题

K题 Headphones

题目大意
总共有n对耳机,Yasa已经拿了k对耳机,NIO至少要拿多少只耳机才能保证比Yasa拿更多对,如果不能就输出-1.

考察内容
数学

分析
如果2*k>n,则不存在,输出-1,否则,最多要拿n-k+k+1只,即n+1只

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n,k;
	while(cin>>n>>k){
		printf("%d",2*k<=n?n+1:-1);
	}
} 

H题 Cutting Papers

题目大意
求图示阴影部分六边形和圆的并集面积
在这里插入图片描述
考察内容
几何

分析
答案为大正方形的一半加上圆的一半,nn/2+pi(n/2)*(n/2)/2

#include<bits/stdc++.h>
using namespace std;

const double pi=acos(-1);

int main(){
	int n;
    cin>>n;
	printf("%lf\n",(double)n*n/2+pi*n*n/8);

}

B题 Watches

题目大意
如果买k块手表,第i块要多花费k*i元,问有m元最多买几块表。

考察内容
二分

分析
在0-n间二分答案

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+7;
int a[N],b[N],n,m;

bool check(int k){
	for(int i=1;i<=n;i++)b[i]=a[i]+k*i;
	sort(b+1,b+n+1);
	int sum=0;
	for(int i=1;i<=k;i++){
		sum+=b[i];
		if(sum>m)return 0;
	}
	return 1;
}

int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	while(cin>>n>>m){
		for(int i=1;i<=n;i++)cin>>a[i];
		int l=1,r=n;
		while(l<=r){
			int k=(l+r)>>1;
			if(check(k))l=k+1;
			else r=k-1;
		}
		cout<<r<<endl;
	}
}

基本题

G题 KFC Crazy Thursday

题目大意
求字符串中以’k’ ‘f’ 'c’结尾的回文子串的数量

考察内容
回文树

分析
模板题

//这注释不写也罢 
#include<bits/stdc++.h>
using namespace std;

const int N=5e5+7;

struct node{
	int next[26];
	int len;
	int sufflink;
	int num;
}tree[N];

int len;
char s[N];
int num;
int suff;

bool addLetter(int pos){
	int cur=suff;
	int curlen;
	int let=s[pos]-'a';
	while(1){
		curlen=tree[cur].len;
		if(pos-1-curlen>=0&&s[pos-1-curlen]==s[pos])break;
		cur=tree[cur].sufflink;
	}
	if(tree[cur].next[let]){
		suff=tree[cur].next[let];
		return 0;
	}
	num++;
	suff=num;
	tree[num].len=tree[cur].len+2;
	tree[cur].next[let]=num;
	if(tree[num].len==1){
		tree[num].sufflink=2;
		tree[num].num=1;
		return 1;
	}
	while(1){
		cur=tree[cur].sufflink;
		curlen=tree[cur].len;
		if(pos-1-curlen>=0&&s[pos-1-curlen]==s[pos]){
			tree[num].sufflink=tree[cur].next[let];
			break;
		}
	}
	tree[num].num=1+tree[tree[num].sufflink].num;
	return 1;
}

void inittree(){
	num=2;suff=2;
	tree[1].len=-1;tree[1].sufflink=1;
	tree[2].len=0;tree[2].sufflink=1;
}

int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	long nk=0,nf=0,nc=0;
	cin>>len>>s;
	inittree();
	for(int i=0;i<len;i++){
		addLetter(i);
		if(s[i]=='k'){
			nk+=tree[suff].num;
		}
		else if(s[i]=='f'){
			nf+=tree[suff].num;
		}
		else if(s[i]=='c'){
			nc+=tree[suff].num;
		}
	}
	printf("%ld %ld %ld\n",nk,nf,nc);
}

C题 Bit Transmission

题目大意
对一个01序列询问,询问的结果最多有一次是错的,问能不能确定序列,可以则输出之,否则输出-1.

考察内容
模拟

分析
满足以下条件输出-1:
1、未询问所有点;
2、存在一点询问得到两种结果数量相同;
3、存在多个点询问得到两种结果;
4、不存在点询问得到两种结果,但是有只询问过一次的点。
否则输出串

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+7;
int a[N][2];
bool m[N];

int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	memset(a,0,sizeof a);
	memset(m,0,sizeof m);
	int n;
	string s;
	cin>>n;
	int op,p=0;
	for(int i=0;i<3*n;i++){
		cin>>op>>s;
		if(!m[op])m[op]=1,p++;
		if(s=="YES")a[op][1]++;
		else a[op][0]++;
	}
	if(p<n){ 
		cout<<-1<<endl;//情况1 
		return 0;
	}
	p=0;
	for(int i=0;i<n;i++){
		if(a[i][1]==a[i][0]){
			cout<<-1<<endl;//情况2 
			return 0;
		}
		if(a[i][1]&&a[i][0])p++;
	}
	if(p>1){
		cout<<-1<<endl;//情况3 
		return 0;
	}
	if(p==0){
		for(int i=0;i<n;i++){
			if(a[i][0]+a[i][1]==1){
				cout<<-1<<endl;//情况4 
				return 0;
			}
		}
	}
	for(int i=0;i<n;i++){
		if(a[i][0]>a[i][1])cout<<0;//输出串 
		else cout<<1;
	}
	cout<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值