小唐开始刷蓝桥(一)2020年第十一届C/C++ B组第二场蓝桥杯省赛真题

目录

  • 一、门牌制作
  • 二、既约分数
  • 三、蛇形填数
  • 四、跑步锻炼
  • 五、七段码
  • 六、并查集
  • 七、回文日期
  • 八、子串分值和
  • 九、平面切分
  • 十、字串排序

上一篇: 呆呆子,这就是小唐的第一篇啦!
下一篇: 小唐开始刷蓝桥(二)2019年第十届C/C++ B组蓝桥杯省赛真题


一、门牌制作

题目描述
蓝要为一条街的住户制作门牌号。这条街一共有2020位住户,门牌号从1到2020编号。小蓝制作门牌的方法是先制作0到9这几个数字字符,最后根据需要将字符粘贴到门牌上,例如门牌1017需要依次粘贴字符1、0、1、7,即需要1个字符0,2个字符1,1个字符7。请问要制作所有的1到2020号门牌,总共需要多少个字符2?

分析分析:
我们一看到这个题目,喔嚯嚯,这不就是直接暴力!!!,我们遍历一整个1~2020,然后在这个循环里面对于每一个数求余,除10统计2的个数就可以了嘛,真的是!

代码:

#include 
using namespace std;
int count=0;//全局变量统计 
void tongji(int i)//判断里面有多少个2 
{
	while(i)
	{
		if(i%10==2)//判断有咩有2 
		count++;
		i=i/10;
	}
}
int main()
{
    for(int i=1;i<=2020;i++)//我们一个一个来不急 
    tongji(i);
    cout<<count;
    return 0; 
}

运行结果

624

二、既约分数

题目描述
如果一个分数的分子和分母的最大公约数是1,这个分数称为既约分数。例如,3/4,5/2,1/8,7/1都是既约分数。请问,有多少个既约分数,分子和分母都是1到2020之间的整数(包括1和2020)

分析分析:
这个题目我一看,又是暴力破解,啊哈哈哈哈哈哈哈哈哈哈,为什么好多暴力的题目,这个既约分数说得这么高级,不就是说你的分子和分母除了1之外没有其他的公约数了嘛,两个for,一个函数判断,直接出

代码:

#include 
using namespace std;
int count=0;
int qiu(int i,int j)
{
	for(int temp=2;temp<=i&&temp<=j;temp++)//temp<=i&&temp<=保证我们两个数的范围 
	{
		if(i%temp==0&&j%temp==0)//当两个条件满足的时候直接结束程序 
		return 0;
	}
	count++;//如果没有结束程序的,那么一定是只可以被1所除的 
	return 0;
}
int main()
{
    for(int i=1;i<=2020;i++)
    for(int j=1;j<=2020;j++)
    qiu(i,j);
    cout<<count;
    return 0; 
}

运行结果

2481215

三、蛇形填数

题目描述
如下图所示,小明用从1开始的正整数“蛇形”填充无限大的矩阵。容易看出矩阵第二行第二列中的数是5。请你计算矩阵中第20行第20列的数是多少?

1 2 6 7 153 5 8 144 9 1310 1211

分析分析:
这个题目我看到时候,一个思路就是,我们创建一个数组,然后依据规律来把这些数输入进去。然后再依据我们的规律来把这个数组位置输出,我们直接看第一行,是不是
列:
偶数=前面的+1
奇数=前面的+(列数-1)*2
斜着下来:
偶数就递增,奇数就递减,而且他们的横纵坐标的和不变的
小唐开始刷蓝桥(一)2020年第十一届C/C++ B组第二场蓝桥杯省赛真题_第1张图片

但是最后的时候,再去看,发现如果把他旋转一下,会简单很多,大家可以去找找规律,也可以和小唐讨论一下喔【手动狗头】

代码:

#include  
using namespace std;
int a[51][51];//因为我们的数组是斜着下来的,所以还需要大一点 
int main(){
    for(int i=1;i<50;i++)
    {
        if(i==1)
        {
            a[1][i]=1;
        }
        else
        {
            if(i%2==0)//判定 
            {
                a[1][i]=a[1][i-1]+1;
            }
            else
            {
                a[1][i]=a[1][i-1]+(i-1)*2;
            }
        }
          if(i%2==1)//给斜着的一列赋值 
        {
            int temp=a[1][i];
            for(int j=1;j<=i;j++)
            {
                a[j][i+1-j]=temp;
                temp--;
            }
        }
        else
        {
            int temp=a[1][i];
            for(int j=1;j<=i;j++)
            {
                a[j][i+1-j]=temp;
                temp++;
            }
        }
    }
    cout<<a[20][20];
}

运行结果

761

四、跑步锻炼

题目描述
小蓝每天都锻炼身体。正常情况下,小蓝每天跑1千米。如果某天是周一或者月初(1日),为了激励自己,小蓝要跑2千米。如果同时是周一或月初,小蓝也是跑2千米。小蓝跑步已经坚持了很长时间,从2000年1月1日周六(含)到2020年10月1日周四(含)。请问这段时间小蓝总共跑步多少千米?
分析分析:
我们在这个题目这里,主要就是要分析他的出去条件,我是直接通过模拟日期一天天的增加,因为每天1km是常态,然后再去判断是不是周一呀(取余运算),是不是月初,这样再来+1km
代码:

#include  
using namespace std;
int count=0;
void rizi(int n,int y,int r,int xi)
{
    while(1)
    {
        r++;
        count++;//每天一跑 
        xi=(xi+1)%7;
        if(xi==1)//周一就加跑一下 
        count++;
//月份判断       
        if(y==1||y==3||y==5||y==7||y==8||y==10||y==12)
        {
            if(r>31)
            {
                y++;
                r=1;
                if(xi!=1)//如果不是周一,就加跑 
                count++;
            }
        }
        if(y==4||y==6||y==9||y==11)
        {
            if(r>30)
            {
                y++;
                r=1;
                if(xi!=1)//如果不是周一,就加跑 
                count++;
            }
        }
        if(n%4==0||n%400==0&&n%100!=0)
        {
            if(r>29&&y==2)
            {
                y++;
                r=1;
                if(xi!=1)//如果不是周一,就加跑 
                count++;
            }
        }
        else
        {
            if(r>28&&y==2)
            {
                y++;
                r=1;
                if(xi!=1)
                count++;
            }
        }     
//年份判断
    if(y>12)
	{
		n++;
		y=1;
		r=1;
	} 
	if(n==2020&&y==10&&r==1)
    break;
    }
    
}
int main(){
    rizi(2000,1,1,6);
    cout<<count+2;//别忘了我们第一天的两公里 
}

运行结果

8879

五、七段码

题目描述
小蓝要用七段码数码管来表示一种特殊的文字。
七段码上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。
例如:b 发光,其他二极管不发光可以用来表达一种字符。
例如:c 发光,其他二极管不发光可以用来表达一种字符。这种方案与上一行的方案可以用来表示不同的字符,尽管看上去比较相似。
例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?
小唐开始刷蓝桥(一)2020年第十一届C/C++ B组第二场蓝桥杯省赛真题_第2张图片

分析分析:
一个巨巨巨巨典型的dfs案例深度搜索我们所有的开灯情况,然后再利用并查集把我们的所有的路劲,来进行一个联通,到时候我们也就只要看,通过我们的查看父节点就可以了,我一开始的一直在想他们路径的重复咱们消去,啊啊啊啊啊啊,并查集学到了。

并查集详解不会的看这个
什么这个题目也可以暴力???
代码:

#include
using namespace std;
int use[8];//看看宝有没有开灯 
int ans,e[8][8]={0},father[8];//ans用于记数, 
void init()//所有联通的路劲 
{
	//连边建图,边相连的为1 
	//a b c d e f g
	//1 2 3 4 5 6 7
	e[1][2]=e[1][6]=1;
	e[2][1]=e[2][7]=e[2][3]=1;
	e[3][2]=e[3][4]=e[3][7]=1;
	e[4][3]=e[4][5]=1;
	e[5][4]=e[5][6]=e[5][7]=1;
	e[6][1]=e[6][5]=e[6][7]=1;
}
int find(int a)//并查集
{
	return (a==father[a])? a:father[a]=find(father[a]);//只有当他自己本省等于本身的时候才是根 
}
void dfs(int d)
{
	if(d>7)//开始筛选数据 
    {
		for(int i=1;i<=7;i++)
        {
            father[i]=i;//注意初始化 
        }
		for(int i=1;i<=7;i++)//循环我们的连通图和判断我们有没有开灯 
        {
		    for(int j=1;j<=7;j++)
            {  
                if(e[i][j]&&use[i]&&use[j])//只有我们开了灯的,还有就是我们选择开灯的,才可以在这一步 
                {
                    int fa=find(i),fb=find(j);
                    if(fa!=fb)// 把所有的路径都连起来 
                    {
                        father[fa]=fb; 
                    }
			    }
            }
			
        }
        int k=0;
		for(int i=1;i<=7;i++){
			if(use[i]&&i==father[i])//看看每一个开灯关灯的结果 ,也就是通过我们这条路可以让灯亮起来 
			k++;
		}
		if(k==1)ans++;//只有一个就统计 
		return;
	}
	//先将我们所有的结果递归出来 
	use[d]=0;//不选 
	dfs(d+1);
	
	use[d]=1;//选 
	dfs(d+1);

}
int main()
{
	init();
	dfs(1);
	cout<<ans<<endl;
	return 0;
}

运行结果

80

六、并查集

题目描述
小蓝给学生们组织了一场考试,卷面总分为100分,每个学生的得分都是一个0到100的整数。如果得分至少是60分,则称为及格。如果得分至少为85分,则称为优秀。请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整数。
【输入格式】 输入的第一行包含一个整数n,表示考试人数。接下来n行,每行包含一个0至100的整数,表示一个学生的得分。
【输出格式】 输出两行,每行一个百分数,分别表示及格率和优秀率。百分号前的部分四舍五入保留整数。
【样例输入】
7
80
92
56
74
88
100
0
【样例输出】
71%
43%
分析分析:
这个好像没有什么要分析的,我们就直接依据提意来,然后把我们的代码打上去就可以了。只有后面的输入输出,懒鬼表示不想写c艹的太长了。
代码:

#include 
#include 
int countyx=0,countjg=0;
using namespace std;
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int cj;
		cin>>cj;
		if(cj>=60)
		{
			countjg++;
		}
		if(cj>=85)
		{
			countyx++;
		}
	}
	printf("%.f%\n",(countjg*100/(float)n));
	printf("%.f%\n",(countyx*100/(float)n));
}

运行结果

根据我们输出案例来
7
80
92
56
74
88
100
0
71%
43%

七、回文日期

题目描述
2020年春节期间,有一个特殊的日期引起了大家的注意:2020年2月2日。因为如果将这个日期按“yyyymmdd”的格式写成一个8位数是20200202,恰好是一个回文数。我们称这样的日期是回文日期。有人表示20200202是“千年一遇”的特殊日子。对此小明很不认同,因为不到2年之后就是下一个回文日期:20211202即2021年12月2日。也有人表示20200202并不仅仅是一个回文日期,还是一个ABABBABA型的回文日期。对此小明也不认同,因为大约100年后就能遇到下一个ABABBABA型的回文日期:21211212即2121年12月12日。算不上“千年一遇”,顶多算“千年两遇”。给定一个8位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA型的回文日期各是哪一天。
分析分析:
别说了,小唐一开始的时候就是在死算,我一个大救命,函数写得又长又多。这不看着前面也有一个日期的题,想着直接套着用。最后写是写出来了,但是是真的太浪费时间了,我去看了一下其他人的解法,这是我看到的最好的
[太巧妙了]
他是直接通过我们的年份来判断是不是回文数,就是说我们把年份转置再和我们的年份相加,再去做一个判断,是真的啊啊啊啊啊,这里就算我们不会用algorithm库也没有很大的关系。
主要是这个思维。当然如果会用更加的快速。像是reverse的直接倒置,substr的分割,stoi字符转数字,to_string(x)哇哇哇哇,又吃了函数的亏
代码:

#include 
#include 
using namespace std;

int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

bool check(int year)
{
	return year % 400 == 0 || year % 4 == 0 && year % 100 != 0;
}

int get_day(int year, int month)
{
	if(month == 2) return 28 + check(year);
	return days[month];
}

int main()
{
	int n;
	cin >> n;
	
	string ans1, ans2;
	bool flag1 = false, flag2 = false;
	for (int i = n / 10000; i <= 9999; i ++)
	{
		string a = to_string(i);
		string b = a;
		reverse(b.begin(), b.end());
		if(a + b <= to_string(n)) continue;
		
		int month = stoi(b.substr(0, 2));
		int day = stoi(b.substr(2, 2));
		if(month < 1 || month > 12) continue;
		if(day < 1 || day > get_day(i, month)) continue;
		
		string s1 = a.substr(0, 2);
		string s2 = a.substr(2, 2);
		if(!flag1) ans1 = a + b, flag1 = true;
		if(!flag2 && s1 == s2 && s1[0] != s1[1]) ans2 = a + b, flag2 = true;

		if(flag1 && flag2) break;
	}
	
	cout << ans1 << endl;
	cout << ans2 << endl;
	return 0;
}

运行结果

输入样例
20200202
输出样例
20211202
21211212

八、子串分值和

ababc
【样例输出】
28
【样例说明】
子串 f值
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1
题目描述
对于一个字符串 S,我们定义 S 的分值 f (S ) 为 S 中出现的不同的字符个
数。例如 f (”aba”) = 2, f (”abc”) = 3, f (”aaa”) = 1。
现在给定一个字符串 S [0::n − 1](长度为 n),请你计算对于所有 S 的非空
子串 S [i:: j](0 ≤ i ≤ j < n), f (S [i:: j]) 的和是多少。
分析分析:
这个题目如果你会使用我们字符串的拆分,那么恭喜你巨巨巨简单,我们就相当于定一个位置不动,然后再用他后面的数字往后面移动
代码:

#include 
#include 
#include 
using namespace std;
int panduan(string a)
{
	int temp=0;
	for(int i=0;i<=a.length();i++)//for循环去找
	{
		for(int j=0;j<a.length();j++)
		{
			if(i==j)//位置相同跳出
			continue;
			if(a[i]==a[j])//遇到相同的就把相同的置0
			{
				a[j]=0;
			}
		}
	}
	for(int i=0;i<a.length();i++)
	{
		if(a[i]!=0)//统计最后不为0的个数
		temp++;
	}
	return temp;
}
int main()
{
	string a;
	cin>>a;
	int sum=0;
	int len=a.length();//获取长度
	for(int i=0;i<=len;i++)//我的这个位置是不动的
	{
		for(int j=1;j<=len;j++)//我玩后面移动
		{
			if((i+j)<=len)//防止重复输出
			{
				string b=a.substr(i,j);//i是他的位置,j是输出几个
//			    cout<
			    sum=sum+panduan(b);//判定
			}
		}
	}
	cout<<sum;
}

运行结果

【样例输入】
ababc
【样例输出】
28
【样例说明】
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1

九、平面切分

题目描述
平面上有 N条直线,其中第 i条直线是 y = Ai*x + B。
请计算这些直线将平面分成了几个部分。
分析分析:

代码:
肝不动了,你们先看看其他的人的解法,我过几天补上去
平面切分答案
运行结果

输入样式:
3
1 1
2 2
3 3
输出样式:
6

十、字串排序

题目描述
小蓝最近学习了一些排序算法,其中冒泡排序让他印象深刻。
在冒泡排序中,每次只能交换相邻的两个元素。小蓝发现,如果对一个字符串中的字符排序,只允许交换相邻的两个字符,则在所有可能的排序方案中,冒泡排序的总交换次数是最少的。
例如,对于字符串 lan 排序,只需要 1 次交换。对于字符串 qiao 排序,总共需要 4 次交换。
小蓝找到了很多字符串试图排序,他恰巧碰到一个字符串,需要 V 次交换,可是他忘了把这个字符串记下来,现在找不到了。
请帮助小蓝找一个只包含小写英文字母且没有字母重复出现的字符串,对该串的字符排序,正好需要 V 次交换。如果可能找到多个,请告诉小蓝最短的那个。如果最短的仍然有多个,请告诉小蓝字典序最小的那个。请注意字符串中可以包含相同的字符。
分析分析:

代码:
肝不动了,你们先看看其他的人的解法,我过几天补上去
运行结果

【输入格式】
输入的第一行包含一个整数V,小蓝的幸运数字。
【输出格式】
题面要求的一行字符串。
【样例输入】
4
【样例输出】
bbaa
【样例输入】
100
【样例输出】
jihgfeeddccbbaa

上一篇: 呆呆子,这就是小唐的第一篇啦!
下一篇: 小唐开始刷蓝桥(二)2019年第十届C/C++ B组蓝桥杯省赛真题

你可能感兴趣的:(遇见蓝桥遇见你,不负代码不负卿,dfs,2020C语言B组,蓝桥杯,算法,c++)