填空题部分
一、在计算机存储中,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;
}