2022牛客多校联赛第五场

比赛传送门

B题 Watches

分析
第一行给定n,m,分别表示n块手表和拥有的钱,第二行,给定n个数a[i],表示每块手表的价格。另外,每块手表会额外花费 i*k的价格,k表示一共买了几块。
代码如下

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

const int N=200010;
const int mod=1e9+7;

int a[N],b[N];

int sum[N];
int n,m;
bool check(int x)
{
	for(int i=1;i<=n;i++) b[i]=a[i]+x*i;
//	for(int i=1;i<=n;i++) cout<<b[i]<<" ";
//	cout<<endl;
	sort(b+1,b+n+1);
	int res=0;
	for(int i=1;i<=x;i++) res+=b[i];
	if(res<=m) return true;
	return false;
}
signed main()
{
	
	while(cin>>n>>m)
	{
		for(int i=1;i<=n;i++) cin>>a[i];
		int l=0,r=n;
		int ans;
	    while(l<=r)
	    {
		    int mid=l+r>>1;
		    if(check(mid)) ans=mid,l=mid+1;
		    else r=mid-1;
		    //cout<<l<<" "<<r<<endl;
 	    }
 	    cout<<ans<<endl;
	}
	
}

C题 Bit Transmission

分析
这里是引用按照题意模拟,看有没有没访问到的地方、YES或NO个数都大于1、YES或NO个数相同、出现大于1个YES和NO都出现过的位置、假如没有YES和NO都出现过的位置,但有某个位置YES和NO只出现了一次,因为错误的地方至多出现一个,无法判断这里是1还是0----以上均输出-1,否则输出ans。
代码如下

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int maxn=100010;
int a[maxn][2];
int b[maxn];
int n;
string s;
int main(){
	while(scanf("%d",&n)!=EOF){
	int x;
	fill(a[0],a[0]+maxn*2,0);
	for(int i=1;i<=3*n;i++){
		scanf("%d",&x);
		cin>>s;
		if(s[0]=='Y'&&s[1]=='E'&&s[2]=='S') a[x][1]++;
		else a[x][0]++;
	}
	bool flag=true;
	int ans=0;
	int ans2=0;
	for(int i=0;i<n;i++){
		if(a[i][0]==a[i][1]&&a[i][1]==0){
			flag=false; 
			break;
		}
		if(a[i][0]==a[i][1]&&a[i][1]==1){
			flag=false;
			break;
		}
		if(a[i][0]>=2&&a[i][1]==0){
			b[i]=0;
		}
		else if(a[i][1]>=2&&a[i][0]==0){
			b[i]=1;
		}
		else if(a[i][0]>=2&&a[i][1]==1){
			b[i]=0;
			ans++;
		}
		else if(a[i][1]>=2&&a[i][0]==1){
			b[i]=1;
			ans++;
		}
		else if(a[i][1]==1&&a[i][0]==0||a[i][1]==0&&a[i][0]==1){
			ans2++;
			continue;
		} 
	}
	if(ans==0&&ans2>=2) flag=0;
	if(ans==0&&ans2==1){
		for(int i=0;i<n;i++){
			if(a[i][1]==1&&a[i][0]==0){
				b[i]=0;
				break;
			}
			else if(a[i][1]==0&&a[i][0]==1){
				b[i]=1;
				break;
			}
		}
	}
	if(ans==1){
		for(int i=0;i<n;i++){
			if(a[i][1]==1&&a[i][0]==0){
				b[i]=1;
			}
			else if(a[i][1]==0&&a[i][0]==1){
				b[i]=0;
			}
		}
	}
	if(flag==false||ans>=2) printf("-1\n");
	else{
		for(int i=0;i<n;i++){
			printf("%d",b[i]);
		}
		printf("\n");
	}
}
	return 0;
}


G题 KFC Crazy Thursday

分析
求以‘k’或‘f’或‘c’为结尾的回文字符串的个数,就是简单的回文判断,不过数据量比较大,那么就分别记录K,F,C出现的位置,再通过判断前后出现的位置之差是不是偶数就可以初步筛选,再配合如果内部存在不是回文的一段,也可以排除一段,这样可以减少很多次循环,减少运行时间,算剪枝的一种
代码如下

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[2000001],s1[2000001];
int len[2000001],n,num[2000001],fail[2000001],last,cur,pos,trie[2000001][26],tot=1;
int getfail(int x,int i)
{
	while(i-len[x]-1<0||s[i-len[x]-1]!=s[i])x=fail[x];
	return x;
}
int main()
{
	int w;
	while(cin>>w)
	{
		scanf("%s",s);
	
    n=strlen(s);
    for(int i=0;i<n;i++) s1[i]=s[i];
    int a1=0,a2=0,a3=0;
    fail[0]=1;len[1]=-1;
    for(int i=0;i<=n-1;i++){
    	//if(i>=1)s[i]=(s[i]+last-97)%26+97; 
    	pos=getfail(cur,i);
        //找到cur的fail链中能匹配i位的最长回文后缀
        if(!trie[pos][s[i]-'a']){
        	fail[++tot]=trie[getfail(fail[pos],i)][s[i]-'a'];
        	trie[pos][s[i]-'a']=tot;
        	len[tot]=len[pos]+2;
            num[tot]=num[fail[tot]]+1;
		}//不存在建立点,存在直接走过去
        cur=trie[pos][s[i]-'a'];
        last=num[cur];
        if(s1[i]=='k') a1+=last;
        if(s1[i]=='f') a2+=last;
        if(s1[i]=='c') a3+=last;
		//printf("%d ",last);	   
	}
	//cout<<endl;
	cout<<a1<<" "<<a2<<" "<<a3<<endl;
	}
	return 0;
}

H题 Cutting Papers

分析
面积为圆的面积+阴影多边形圆外面的面积,即整个圆的面积+(四个三角形面积-半圆的面积)
代码如下

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define pi 3.14159265358979
const int N=200010;
const int mod=1e9+7;
 
int a[N],b[N];
int cnta[N],cntb[N];
int sum[N];
signed main()
{
    int n;
    while(cin>>n)
    {
        double r=n/2.0;
        printf("%.12lf\n",pi*r*r/2.0+2*r*r);
         
    }
     
}

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define pi 3.14159265358979
const int N=200010;
const int mod=1e9+7;
 
int a[N],b[N];
int cnta[N],cntb[N];
int sum[N];
signed main()
{
    int n;
    while(cin>>n)
    {
        double r=n/2.0;
        printf("%.12lf\n",pi*r*r/2.0+2*r*r);
         
    }
     
}

K题 Headphones

分析
可知一共有N对蓝牙耳机,Yasa拿走了k对耳机,那么剩下了N-k对耳机=2*(N-k)个耳机,如果要组成k+1对耳机,那么根据鸽巢原理,需要拿N-k+k+1->N+1个耳机保证能组成k+1对耳机,那么最少能组成k+1对耳机的条件就是剩下的耳机对数起码要有k+1对。
代码如下

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

const int N=200010;
const int mod=1e9+7;

int a[N],b[N];

int sum[N];
int n,k;

signed main()
{
	
	while(cin>>n>>k)
	{
		if(2*k+1<=n)
		{
			int t=n-2*k-1;
			cout<<(k+1)*2+t<<endl;
		}
		else cout<<-1<<endl;
	}
	
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值