2023省赛A组

2023省赛A组

题目来源:去洛谷上搜索“蓝桥杯 2023 省 A”即可

A.幸运数(填空)

因为是填空只要把结果跑出来就行,不用太在意会TLE

知识点:前缀和

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e8;
bool check(int x)
{
    int a[10]={0};
    int num=0;
    while(x)
    {
        num++;
        a[num]=a[num-1]+(x%10);
        x/=10;
    }
    if(num%2!=0)return false;
    if(a[num/2]!=(a[num]-a[num/2]))return false;
    return true;
}
int main()
{
    int sum=0;
    for(int i=1;i<=N;i++)
    {
        if(check(i))
        {
            sum++;
        }
    }
    cout<<sum<<endl;
    return 0;
}

B.有奖问答(填空)

说实话现在我还没太懂这一块,我开始是这么写的。

在网上看题解有人是用搜索暴力写的,不如用循环的写法,可以锻炼一下数学。

首先指定是在最后连续7次,而且只能连续7次,7次之前一定是一个答错的,或者从一开始就答对7次。

所以说这7次的第一个的位置在1~24,因为位置1和位置2各有一种。所以直接令初始就为2.

所以说填满7个答对及前面的答错,还剩n个位置可以随便填,但!不能随便填,因为如果出现连续10个的情况,答题就结束了。所以必须减去存在有连续10个及10个以上答对题的情况。其余的见注释。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n=0,sum=2;
    for(int i=3;i<=24;i++)//i是连续7个第一个位置在30个位置的哪
    {
        n=i-2;//n:填满之后还有多少个空位
        int ans=(1<<n);//初始先随便填,之后再减去情况
        if(n>=10){//只有空位>=10才会出现连续10个的情况
            for(int j=10;j<=n;j++)//最多可以连续多少个
            {
                if(j==n)ans--;//顶满
                else
                {
                    int k = n-j-1;
                    if(k>=0)ans-=2*(1<<k);//连续答对的全部在左边或者全部在右边而且相邻的那个一定是答错,全部在左边一种,全部在后边一种,一共两种,每种有(n-j-1)个空位,可以画个图看一下
                    k--;
                    if(k>=0)ans-=(k+1)*(1<<k);//连续答对的不顶格,左右都为答错,所以空格数(待填的)为n-j-2,加上如果有n-j-2个空格,那这个可以滑动n-j-2+1次,所以这么算
                }
            }
        }
        sum+=ans;
        cout<<"位置在"<<i<<"共有"<<ans<<endl;
        
    }
    sum+=6;//23有1种,24有5种(超过两个连续10个及以上的,只有23,24才会出现两块连续10个及以上,这部分被重复减去了)
    cout<<sum<<endl;
    return 0;
}

后来发现把24的情况交上去就过了emmmmm,所以意思是只能在最后全答对吗

AC代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n=22;//n:填满之后还有多少个空位
    int ans=(1<<n);
    if(n>=10){
        for(int i=10;i<=n;i++)//最多可以连续多少个
        {
            if(i==n)ans--;
            else
            {
                int k = n-i-1;
                if(k>=0)ans-=2*(1<<k);
                k--;
                if(k>=0)ans-=(k+1)*(1<<k);
            }
        }
    }
    ans+=5;//23有1种,24有5种
    cout<<ans<<endl;
    return 0;
}

C.平方差

简单的数学变换,x=(y-z)(y+z),设n=y-z,m=y+z,m-n=2z,所以m,n同奇或者同偶(因为它俩的差为偶数)。

结论就是只要x能表示成两个奇数的和或者两个偶数的和就行。

仔细想一下x如果为奇数就一定可以表示成1*x=x,符合要求

如果是偶数不能表示成奇数x奇数,一定是需要满足表示成偶数x偶数,因数有两个偶数所以为4的倍数。

所以满足要求的x包括奇数和4的倍数的偶数。

#include<bits/stdc++.h>
using namespace std;
int getjishu(int l,int r)
{
    //使得两端都为奇数
    if(l%2==0)l++;
    if(r%2==0)r--;
    if(r<l)return 0;
    return (r-l)/2+1;
}
int getoushu(int l,int r)
{
    //使得两端都为4的倍数
    if(l%4!=0)
    {
        l+=(4-l%4);
    }
    if(r%4!=0)
    {
        r-=(r%4);
    }
    if(r<l)return 0;
    return (r-l)/4+1;
    
}
int main()
{
    int l,r;
    cin>>l>>r;
    cout<<getjishu(l, r)+getoushu(l, r)<<endl;;
    return 0;
}

D. 更小的数

这题居然是黄题,有点离谱。数据范围挺小的,不会超时。

直接暴力遍历子串的首尾,并且往里面收缩,如果说两端一致,就往中间收缩,因为首尾相同,但是中间有子串满足转换了变小也满足题意,比如一个子串是这样的:1234121,这个子串首尾是对称的,但是把对称的首尾剥离开,就变成了341,满足反转了变小,所以说1234121这个子串也满足题意。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string s;
    cin>>s;
    int len = s.size();
    int sum=0;
    for(int i=0;i<len;i++)
    {
        for(int j=i+1;j<len;j++)
        {
            int l=i,r=j;
            while(l>=0&&r<len&&l<r)//满足必要条件
            {
                if(s[r]<s[l])sum++;
                if(s[r]!=s[l])break;//如果说又不一样的收缩就不用继续了
                l++;r--;
            }
        }
    }
    cout<<sum<<endl;
    return 0;
}

E.颜色平衡树

这道题是蓝题,对于几年前的我来说也是不是那么好写的。所以先写一个能过60%样例的暴力版本。

思路就是用dfs统计子树的各种颜色个数,写一个check函数统计颜色个数相同的结点

能过60%的测试点

#include<bits/stdc++.h>
using namespace std;
const int N = 5009;
vector<int>ve[N];
int c[N];
int color[N][N];
int max_color=-1;
void dfs(int x)
{
    color[x][c[x]]++;
    for(int i=0;i<ve[x].size();i++)
    {
        int to = ve[x][i];
        dfs(to);
        for(int j=1;j<=max_color;j++)
        {
            color[x][j]+= color[to][j];
        }
        
    }
}
bool check(int x)
{
    int first = -1;
    for(int i=1;i<=max_color;i++)
    {
        if(first == -1 && color[x][i] !=0)
            first = color[x][i];
        if(first!=-1 && color[x][i]!=0 && color[x][i]!=first)//cxl
            return false;
    }
    return true;
}
int main()
{
    int n,x;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>c[i]>>x;
        ve[x].push_back(i);
        max_color = max(max_color,c[i]);
    }
    dfs(1);
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        if(check(i))sum++;
    }
    cout<<sum<<endl;
    return 0;
}
posted @   wlqtc  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示