蓝桥杯第十一届软件类校内模拟赛题解(上)

填空题部分

一、在计算机存储中,15.125GB是多少MB?

(15.125GB * 1024 = 15488MB)

二、1200000有多少个约数(只计算正约数)。

写个python脚本算一下得 (96)

cnt=0
for i in range(1,1200001):
    if not 1200000%i:
        cnt=cnt+1
print(cnt)

三、一棵包含有2019个结点的树,最多包含多少个叶结点?

昊神告诉我这叫星图,除父节点外全部是同辈的叶子节点,答案 (2018)

四、在1至2019中,有多少个数的数位中包含数字9?
注意,有的数中的数位中包含多个9,这个数只算一次。例如,1999这个数包含数字9,在计算只是算一个数。

写个程序算一下即可,答案 (544)

for (int i=1;i<=2019;i++) {
    int x=i,fl=0;
    while (x) {
        if (x%10==9) { fl=1; break; }
        x/=10;
    }
    if (fl) sum++;
}

编程题(一)

问题描述

小明对类似于 (hello) 这种单词非常感兴趣,这种单词可以正好分为四段,第一段由一个或多个辅音字母组成,第二段由一个或多个元音字母组成,第三段由一个或多个辅音字母组成,第四段由一个或多个元音字母组成。
给定一个单词,请判断这个单词是否也是这种单词,如果是请输出yes,否则请输出no。
元音字母包括 (a, e, i, o, u) ,共五个,其他均为辅音字母。

输入格式

输入一行,包含一个单词,单词中只包含小写英文字母。

输出格式

输出答案,或者为 (yes) ,或者为 (no)

评测用例规模与约定

对于所有评测用例,单词中的字母个数不超过 (100)

——————————————————————————————

模拟题意即可,四段分开判断,遇到连续的元音/辅音就不断读入。

(f) 数组标志对应段的合法性,要注意最后还要判断一下尾部的合法性。

代码如下:

#include <bits/stdc++.h>
using namespace std;
char str[233];
int f[4],pos,len;
inline bool isy(char x) {
	if (x=='a' || x=='e' || x=='i' || x=='o' || x=='u')
		return true;
	else return false;
}
int main() {
	scanf("%s",str),len=strlen(str);
	while (!isy(str[pos]) && pos<len) f[0]=true,pos++;
	while (isy(str[pos]) && pos<len) f[1]=true,pos++;
	while (!isy(str[pos]) && pos<len) f[2]=true,pos++;
	while (isy(str[pos]) && pos<len) f[3]=true,pos++;	
	puts(f[0]&&f[1]&&f[2]&&f[3]&&len==pos?"yes":"no");
	return 0;
}

编程题(二)

问题描述

在数列 (a[1], a[2], ..., a[n]) 中,如果对于下标 (i, j, k) 满足 (0<i<j<k<n+1)(a[i]<a[j]<a[k]),则称 (a[i], a[j], a[k]) 为一组递增三元组,(a[j]) 为递增三元组的中心。

给定一个数列,请问数列中有多少个元素可能是递增三元组的中心。

输入格式

输入的第一行包含一个整数 (n)

第二行包含 (n) 个整数 (a[1], a[2], ..., a[n]) ,相邻的整数间用空格分隔,表示给定的数列。

输出格式

输出一行包含一个整数,表示答案。

评测用例规模与约定

对于 (50%) 的评测用例,(2 <= n <= 100)(0 <= Num <= 1000)
对于所有评测用例,(2 <= n <= 1000)(0 <= Num <= 10000)

——————————————————————————————
其实就是叫我们求前面有比它小的,后面有比它大的的数的个数,想起了NOIP2014的珠心算试验...

因为 (n<=1000) ,所以可以直接用 (O(n^2)) 暴力找。

代码如下:

#include <bits/stdc++.h>
#define MAXN 10007
using namespace std;
int n,ans,a[MAXN];
int main() {
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int i=1;i<=n;i++) {
		bool f1=false,f2=false;
		for (int j=1;j<i;j++)
			if (a[j]<a[i]) { f1=true; break; }
		for (int j=i+1;j<=n;i++)
			if (a[j]>a[i]) { f2=true; break; }
		if (f1&&f2) ans++; 
	}
	printf("%d",ans);
	return 0;
}

当然也可以用 (ST) 表把复杂度优化为 (O(nlogn))

代码如下:

#include <bits/stdc++.h>
#define MAXN 10007
#define INF 0x3f3f3f3f
using namespace std;
int n,ans,t1[MAXN][20],t2[MAXN][20];
inline void init() {
    for (int j=1;j<=log2(n);j++)
        for (int i=1;i<=n-(1<<j)+1;i++) {
            t1[i][j]=min(t1[i][j-1],t1[i+(1<<(j-1))][j-1]);
			t2[i][j]=max(t2[i][j-1],t2[i+(1<<(j-1))][j-1]);
		}
}
inline int q1(int l,int r) {
    if (l>r) return INF;
	int t=log2(r-l+1);
    return min(t1[l][t],t1[r-(1<<t)+1][t]);
}
inline int q2(int l,int r) {
    if (l>r) return -1;
    int t=log2(r-l+1);
    return max(t2[l][t],t2[r-(1<<t)+1][t]);
}
int main() {
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d",&t1[i][0]),t2[i][0]=t1[i][0];
	init();
	for (int i=1;i<=n;i++)
		if (q1(1,i-1)<t1[i][0] && q2(i+1,n)>t1[i][0]) ans++; 
	printf("%d",ans);
}

最优是 (O(n)) 的,用两个数组分别从头和尾依次记录一下当前最小或最大值即可,也比较简单就不补代码了。(感谢@11eyes 提醒)。


编程题(三)

问题描述

一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数,例如 (1135) 是一个数位递增的数,而 (1024) 不是一个数位递增的数。

给定正整数 (n) ,请问在整数 (1)(n) 中有多少个数位递增的数?

输入格式

输入的第一行包含一个整数 (n)

输出格式

输出一行包含一个整数,表示答案。

评测用例规模与约定

对于 (40\%) 的评测用例,(1 <= n <= 1000)
对于 (80\%) 的评测用例,(1 <= n <= 100000)
对于所有评测用例,(1 <= n <= 1000000)

——————————————————————————————

(40) 分的做法就是在 ((1,n)) 里枚举每一个数,然后判断每位是否递增。

但是直接构造数位递增的数显然是更优的,这里用递归进行逐位构造。

边界条件:(num>n)(i=9)

(我也不知道 (80) 分的范围有啥用

代码如下:

#include <bits/stdc++.h>
int n,ans=0;
using namespace std;
void dfs(int num) {
	for (int i=num%10?num%10:1;i<=9;i++)
		if (num*10+i<=n) ans++,dfs(num*10+i);
}
int main() {
	scanf("%d",&n),dfs(0);
	printf("%d",ans); 
	return 0;
}

下转:蓝桥杯第十一届软件类校内模拟赛题解(下)

原文地址:https://www.cnblogs.com/zhwer/p/12496857.html