“蔚来杯“2022牛客暑期多校训练营5(B,C,G,H)

B题

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

有一说一,明明那么简单的题目,为什么描述的那么随便,理解题目就花了我们好久,浪费了不少时间,但后面出题人一直滑跪也是厉害,理解题目后就可以很直接联想到贪心,但过不了。我们一直以为是贪心策略有问题,尝试改进了2遍没什么作用。之后想到了二分答案和排序,就AC了。

#include<bits/stdc++.h>
using namespace std;
struct op{
	int num,pri;
};
op a[100005];
bool cmp(op x,op y)
{
	if (x.pri<y.pri)
		return true;
	else
		return false;  
}
int n,m,k,b[100005],w;
int main(){
	 while(scanf("%d%d",&n,&m)!=EOF){
	 	w=0;
	 	for (int i=1;i<=n;i++){
	 	 	scanf("%d",&a[i].pri);
	 	 	a[i].num=i;
			a[i].pri=a[i].pri+i; 
		}
		k=1; 
		while (1){
			w=0;
			sort(a+1,a+1+n,cmp);
			for (int i=1;i<=k;i++){
				w=w+a[i].pri;
			}
			if (w>m){
				cout<<k-1<<endl;
				break;
			}
			for (int i=1;i<=n;i++)
				a[i].pri=a[i].pri+a[i].num;
			k++;
		} 
    }
	return 0; 
}

C题

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

比赛的时候我捣鼓后面几题了,这题是队友AC的,不过结束后回头看,难度还可以(队友还是太强了)。

#include<bits/stdc++.h>
using namespace std;
int n;
const int N=1e5+10;
int cnt1[N],cnt2[N];
int main()
{
    cin.tie(0);
    cout.tie(0);
    while(cin>>n){
        memset(cnt1,0,sizeof cnt1);
        memset(cnt2,0,sizeof cnt2);
        for(int i=1;i<=3*n;i++){
            int a;
            string s;
            cin>>a>>s;
            if(s=="YES") cnt1[a]++;
            else cnt2[a]++;
        }
       // for(int i=0;i<n;i++) cout<<cnt1[i]<<" "<<cnt2[i]<<endl;
        string s;
        int res=0;
        bool flag=true;
        for(int i=0;i<n;i++){
            if(res>1) {
                flag=false;
                puts("-1");
                break;
            }
            if(cnt1[i]==0&&cnt2[i]==0) {
                puts("-1");
                flag=false;
                break;
            }
            else if(cnt1[i]){
                if(cnt2[i]==0) s+='1'; 
                else if(cnt2[i]){
                    if(cnt2[i]==1&&cnt1[i]==1){
                        flag=false;
                        puts("-1");
                        break;
                    }
                    else if(cnt2[i]>1&&cnt1[i]>1){
                        flag=false;
                        puts("-1");
                        break;
                    }
                    else if(cnt2[i]>1&&cnt1[i]==1){
                        s+='0';
                        res++;
                        if(res>1) {
                flag=false;
                puts("-1");
                break;
            }
                    }
                    else if(cnt2[i]==1&&cnt1[i]>1){
                        s+='1';
                        res++;
                        if(res>1) {
                flag=false;
                puts("-1");
                break;
            }
                    }
                }
            }
            else if(cnt2[i]){
                s+='0';
            }
            
    }
        reverse(s.begin(),s.end());
        if(flag) cout<<s<<endl;
    }
}

G题

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

#include<bits/stdc++.h>
using namespace std;
int n,k[500005],f[500005],c[500005],km,fm,cm,l,r;
//map<int,int>kp,fp,cp;
//int kp[10005][10005],fp[10005][10005],cp[10005][10005];
long long int ansk,ansf,ansc;
char s[500005];
int main(){
	while(scanf("%d",&n)!=EOF){
		km=0;fm=0;cm=0;
		for(int i=1;i<=n;i++){
			cin>>s[i];	
			//cout<<s[i];
			if (s[i]=='k'){
				km++;
				k[km]=i;
			//	cout<<km<<" ";
			}
			if (s[i]=='f'){
				fm++;
				f[fm]=i;
			}
			if (s[i]=='c'){
				cm++;
				c[cm]=i;
			}
			
		}
		ansk=km;
		ansf=fm;
		ansc=cm;
	//	cout<<ansk;
		for (int i=1;i<=km-1;i++){
			for (int j=1;j<=km-i;j++)
			{
				//if (i>=3 && kp[j+1][j+i-1]==0)
				  //  continue;
				if (i>=3 && k[j+1]-k[j]!=k[j+i]-k[j+i-1])
					continue;
				if (i==2 && k[j+1]-k[j]!=k[j+2]-k[j+1])
					continue;
				l=k[j],r=k[j+i];
				while(1){
					if (l>=r){
					//	kp[j][j+i]=1;
						ansk++;
						break;
					}
					l++;
					r--;
					if (s[l]!=s[r])
						break;
				}
			}
		}
		//cout<<ansk;
			for (int i=1;i<=fm-1;i++){
			for (int j=1;j<=fm-i;j++)
			{
			//	if (i>=3 && fp[j+1][j+i-1]==0)
			//	    continue;
				if (i>=3 && f[j+1]-f[j]!=f[j+i]-f[j+i-1])
					continue;
				if (i==2 && f[j+1]-f[j]!=f[j+2]-f[j+1])
					continue;
				l=f[j],r=f[j+i];
				while(1){
					if (l>=r){
					//	fp[j][j+i]=1;
						ansf++;
						break;
					}
					l++;
					r--;
					if (s[l]!=s[r])
						break;
				}
			}
		}
			for (int i=1;i<=cm-1;i++){
			for (int j=1;j<=cm-i;j++)
			{
			//	if (i>=3 && cp[j+1][j+i-1]==0)
			//	    continue;
				if (i>=3 && c[j+1]-c[j]!=c[j+i]-c[j+i-1])
					continue;
				if (i==2 && c[j+1]-c[j]!=c[j+2]-c[j+1])
					continue;
				l=c[j],r=c[j+i];
				while(1){
					if (l>=r){
					//	cp[j][j+i]=1;
						ansc++;
						break;
					}
					l++;
					r--;
					if (s[l]!=s[r])
						break;
				}
			}
		}
	  cout<<ansk<<" "<<ansf<<" "<<ansc<<endl;
	}
	return 0;
}

H题

面积为圆的面积+阴影多边形圆外面的面积,即整个圆的面积+(四个三角形面积-半圆的面积)

谢谢出题人的错误样例,让我对我的代码产生了2个小时的误解,不过在更改样例之后,就可以很快的过了,本身就是一道签到题,硬生生卡了好久。

#include<bits/stdc++.h>
using namespace std;
double pi=3.1415926535;
long double r,s,ans;
int n;
int main()
{
	cin>>n;
//	r=1.0*sqrt(2)*n*1.0/2;
    r=1.0*n/2.0;
	s=pi*r*r;
	ans=s-(0.5*s-(1.0*n/2)*(1.0*n/2));
	printf("%.6Lf",ans);
	return 0; 
}

K题

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

也是一道简单题,但也是因为题目描述问题,我们理解错了3次,导致wa了3次,真的难受。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,k;
    while(cin>>n>>k){
    if(n-k>=k+1) {
        int res=n-k;
        cout<<(n+1)<<endl;
    }
    else puts("-1");
    }
}

这次的比赛就不补题了,没意思,好多是原题,没意义。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值