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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理