C++牛客周赛43题目分享(3)小红平分糖果,小红的完全平方数,小苯的字符串变化,小红的子数组排列判断

目录

​编辑

1.前言

2.四道题目

2.1小红平分糖果

2.1.1题目描述

2.1.2输入描述

2.1.3输出描述

2.1.4示例

2.1.5代码

2.2小红的完全平方数

2.1.1题目描述

2.1.2输入描述

2.1.3输出描述

2.1.4示例

2.1.5代码

2.3小苯的字符串变化

2.1.1题目描述

2.1.2输入描述

2.1.3输出描述

2.1.4示例

2.1.5代码

2.4小红的子数组排列判断

2.1.1题目描述

2.1.2输入描述

2.1.3输出描述

2.1.4示例

2.1.5代码

3.小结


1.前言

哈喽大家好啊,就在刚刚的周日,结束了牛客周赛 Round 43,今天继续为大家分享一些题解,希望对大家有所帮助,也请大家多多支持我哦~

2.四道题目

2.1小红平分糖果

2.1.1题目描述

2.1.2输入描述

2.1.3输出描述

2.1.4示例

2.1.5代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int main(){
	int n=0;
    scanf("%d",&n);
    if(n%2==0)printf("%d %d",n/2,n/2);
    else printf("-1");
	return 0;
} 

第一道题就是一道简单的签到题,认真审题就没有问题~ 

2.2小红的完全平方数

2.1.1题目描述

2.1.2输入描述

2.1.3输出描述

2.1.4示例

2.1.5代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

void func()
{
    long long x;
    cin>>x;
    long long l=sqrt(x);
    long long r=l+1;
    if((x-l*l)%2==0)cout<<(x-l*l)/2;
    else cout<<(r*r-x)/2;
    
}
int main()
{
    func();
    return 0;
}

第二道题考了一道有关完全平方数的问题:

在解决这道题之前,我们需要先明白完全平方数的一个性质,每一个完全平方数都是由连续的自然数平方得出,由于自然数的顺序是奇数偶数交错,且奇数乘以奇数仍未奇数,偶数乘以偶数仍未偶数,因此,每一个完全平方数也是奇数偶数相交错


在知晓这一个性质之后就可以开始敲代码了,先寻找输入的这个数在哪俩个相邻的完全平方数之间,然后寻找该数离哪一个完全平方数的距离是偶数,最后输出即可。

以上代码中是直接打印出了模拟出来的结果,可以先自己在演草本上写写。

2.3小苯的字符串变化

2.1.1题目描述

2.1.2输入描述

2.1.3输出描述

2.1.4示例

2.1.5代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

const int N=100005;
char s[N];
int a[N],b[N];
int m=0,locate=0,ans=1e9;

int main(){
    scanf("%s",s);
	m=strlen(s);
    if(s[0]>='a'&&s[0]<='z')a[0]=1;

    for(int i=1;i<m;i++){
        if(s[i]>='a'&&s[i]<='z'){
            a[i]=a[i-1]+1;
        }
        else a[i]=a[i-1];
    }
    
    for(int j=m-1;j>=0;j--){
        if(s[j]>='A'&&s[j]<='Z'){
            b[j]=b[j+1]+1;
        }
        else b[j]=b[j+1];
    }
    
    for(int n=0;n<m-1;n++){
        ans=min(ans,a[n]+b[n+1]);
    }
    cout<<ans<<endl;
	return 0;
} 

这一道题有一点前缀和的感觉,接下来是题目思路:

根据题意,任何一个位置都可以作为那一个“分界点”,即前面小写字母(包括本分界点)都变成大写字母,后面的大写字母(不包括本分界点)都变成小写字母。因此根据这个逻辑,我们可以将每一个字母都作为“分界点”并利用循环分别计算前后大小写字母个数。


先按照题意输入,然后先进行第一个字母的判断(因为循环处可能会出现越界,所以将边界点拿出来单独处理),接着俩个循环(一个正向,一个反向)分别计算字母数量,最后再利用一个循环取所有分界点中,俩个字母数目相加的最小值,最后输出即可。

2.4小红的子数组排列判断

2.1.1题目描述

2.1.2输入描述

2.1.3输出描述

2.1.4示例

2.1.5代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int n=0,k=0;//数组大小与连续子数组大小
int a[100005];//存储定义排列
int b[100005];//存储当下数字状态
int num=0;//存储当下k数组中有多少不同的数字
int ans=0;//记录答案

int main(){
	scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++)scanf("%d",&a[i]);
    
    for(int i=0;i<k;i++){
        b[a[i]]++;
        if(b[a[i]]==1)num++;
    }
    if(num==k)ans++;//判断前k个是否满足题意
    
    for(int i=k;i<n;i++){
        b[a[i-k]]--;
        if(b[a[i-k]]==0)num--;
        b[a[i]]++;
        if(b[a[i]]==1)num++;
        if(num==k)ans++;
    }
    cout<<ans<<endl;
	return 0;
} 

 这道题当时拿到手里的时候,感觉题目很清晰但自己唯一能想到的方法就是暴力(就是一直不断利用for循环),但我也知道这样也会爆TLE,所以接下来给大家分享一个比较良好的算法整体思路如下:


先来为大家讲解一下题意:

我这里输入的数组与k值分别为:

 数组:3 2 3 1 2 3 2 1 2 3 1 3

 k值:3

我们从第一个开始往后模拟(每次往后递推一位):

3 2 3不满足。2 3 1满足。3 1 2满足。1 2 3满足。2 3 2不满足。

3 2 1满足。2 1 2不满足。1 2 3满足。2 3 1满足。3 1 3不满足。

综上所述,输出结果应为6。


从以上的模拟我们应该能发现规律,每次往后地推一位只是少了第一个数多了最后一个数,在判断该子序列是否满足题意时也大可不必采用for循环大法,可以通过判断每位数出现的次数,如果出现的次数num刚好等于k,那么ans++;相反如果子序列中有重复的数,num<k,那么ans不做处理,最后输出即可。


(还有一点也需要提到的是,如果输入的数中有大于k的数字,应当continue,但对该题无影响,这样操作更加严谨)

3.小结

今天的这四道题虽然题目较为简单,但对平时解题时思路的拓展仍有借鉴意义,看完了不要忘了点个赞喔。感谢大家的支持~

  • 107
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 49
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃烤鸡翅的酸菜鱼

希望大家对我多多支持喔~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值