编程笔记|蓝桥杯模拟赛收获(5-7题)
本文非原创,仅为个人的学习笔记,借鉴了一些文章链接如下。
2020年蓝桥杯模拟赛解题报告(CPP版本)
C++ 中string.find() 函数的用法总结
C++ getline函数用法详解
C++ 定义数组 传递数组
此外还有一本书《c++语言程序设计(第四版)》(郑莉,董渊)
第五题
一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数,例如1135是一个数位递增的数,而1024不是一个数位递增的数。
给定正整数 n,请问在整数 1 至 n 中有多少个数位递增的数?
代码:
#include
#include
void work();
using namespace std;
int main() {
while (1)//死循环为测试用
work();
return 0;
}
void work() {
int n;
cin >> n;
int ans = 0;
for (int i = 1; i <= n; ++i) {
char s[8];
sprintf(s, "%d", i);
bool flag = 1;
for (int j = 1; j < strlen(s); ++j) {
if (s[j - 1] > s[j]) {
flag = 0;
break;
}
}
if (flag)
ans++;
}
cout << ans << endl;
}
分析:
这道题我应该写出来了,但是老师的代码肯定好一些,毕竟用了我不会用的sprintf函数。
第六题
在数列 a[1], a[2], …, a[n] 中,如果对于下标 i, j, k 满足 0 给定一个数列,请问数列中有多少个元素可能是递增三元组的中心。
分析:
这题我应该也做对了,我是用c语言编写的,因为我连c++的数组都没怎么学过。。。老师这里用c++,我可以学习。
具体思路:
就是向前遍历找到一个比此数小的一个数,向后遍历,找到一个比他大的。通过分析复杂度应为,因为测试数据最大是1000,所以能在一秒之内解决战斗。。。照抄老师原话,我比赛的时候从没想过,会不会时间不够
代码:
#include
void work();
using namespace std;
int main() {
while(1)//死循环为测试用
work();
return 0;
}
void work() {
int n, ans = 0;
cin >> n;
int *data = new int[n];
for (int i = 0; i < n; ++i) {
cin>>data[i];
}
for (int j = 1; j < n-1; ++j) {
int hasSmall=0;
for (int i = 0; i
数组定义
1.静态分配
int array[10];
2.动态分配
- c语言
//定义
int arraysize;//元素个数
printf("请输入数组的大小:");
scanf("%d",&arraysize);
int *array;//指针指向数组
array=(int *)malloc(arraysize *sizeof(int));//动态内存分配
//释放
free(array);
- c++
一维:
//定义
int arraysize;//元素个数
cout<<"请输入数组的大小:";
cin>>arraysize;
int *array;//指针指向数组
array=new int[arraysize]; //动态内存分配
//释放
delete []array;
最好释放,但是不释放也没什么关系,他在结束之后不会占用内存,网上是这么说的。
二维:
//定义
cin>>row >>col ;
int **p2 ;
p2 = new int*[row] ;
for( i = 0 ; i < row ; i ++ )
p2[i] = new int[col] ;
//释放二维数组
for( i = 0 ; i < row ; i ++ )
delete []p2[i] ;
delete []p2 ;
三维:
参考二维,而且你暂时也用不到啊。
第七题
小明对类似于 hello 这种单词非常感兴趣,这种单词可以正好分为四段,第一段由一个或多个辅音字母组成,第二段由一个或多个元音字母组成,第三段由一个或多个辅音字母组成,第四段由一个或多个元音字母组成。
给定一个单词,请判断这个单词是否也是这种单词,如果是请输出yes,否则请输出no。
元音字母包括 a, e, i, o, u,共五个,其他均为辅音字母。
分析:
找到第一个元音的下标index1,必须大于0,且能找到
沿着index1继续找下一个非元音得到index2,必须能找到
沿着index2继续找下一个元音得到index3,必须能找到
最后判断index3-1位置的字符应该是从后往前第一个非元音(因为index3及以后的字符都必须是元音了)
拿hello举例子
第一个元音为e,如果e的index为零,说明前面没有辅音串,所以退出
如果不为零,继续找找到下一个非元音位置,这个index应该是这个字
符串的第三段位置了,再找下一个元音,得到的index,应该是逆序找
的第一个辅音,因为如果满足的话“辅元辅元”倒过来是“元辅元辅”。
到这里我只能说一句妙啊。
代码:
#include
int work();
using namespace std;
int main() {
while (1) { //死循环是为了测试
if (work())
cout << "yes" << endl;
else
cout << "no" << endl;
}
return 0;
}
int work() {
string word;
const string yuan = "aeiou";
getline(cin, word);
if (word.size() < 4)
return 0;
//第一个元音字符的pos
int index1 = word.find_first_of(yuan, 0);
if (index1 == 0 || index1 == string::npos) {
return 0;
}
//之后第一个非元音
int index2 = word.find_first_not_of(yuan, index1 + 1);
if (index2 == word.size() - 1 || index2 == string::npos) {
return 0;
}
//之后第一个元音
int index3 = word.find_first_of(yuan, index2 + 1);
if (index3 == string::npos) {
return 0;
}
if (index3 - 1 != word.find_last_not_of(yuan)) {
return 0;
}
return 1;
}
- getline()
c++中的cin虽然有其简洁的优点,但也不能用的时候:
当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格、制表符或换行符)。一旦它接触到第一个非空格字符即开始阅读,当它读取到下一个空白字符时,它将停止读取。
下面的语句将为你的理解带来帮助。
// This program illustrates a problem that can occur if
// cin is used to read character data into a string object.
#include
#include // Header file needed to use string objects
using namespace std;
int main()
{
string name;
string city;
cout << "Please enter your name: ";
cin >> name;
cout << "Enter the city you live in: ";
cin >> city;
cout << "Hello, " << name << endl;
cout << "You live in " << city << endl;
return 0;
}
运行结果是这样的:
Please enter your name: John Doe
Enter the city you live in: Hello, John
You live in Doe
为什么在Enter the city you live in的时候你输入都没输入就已经跳到下一行语句了呢?
因为上次cin读入的终点在你的John的后面,在cin第二次出现时,他就从那个地方再开始读后面的Doe\n。这是我根据结果进行的猜测,不知道对不对,
为了解决这个问题,可以使用一个叫做 getline 的 C++ 函数。此函数可读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中。
getline 函数如下所示:
getline(cin,inputline)
inputline是你想输入的string型的变量名
这个函数可以完美的解决之前的问题。
其次参考程序用到的函数有
函数名 |
---|
string.size() |
string.find_first_of() |
string.find_first_not_of() |
string.find_last_of() |
string.find_last_not_of() |
此外还有string.rfind()函数返回的是从右向左查找的序数。
注意
string.find 和以上函数表中的函数有一点本质区别:
下面举一例说明:
-
如果string sub = ”abc“;
string s = ”cdeabcigld“;
s.find(sub) , s.rfind(sub) 这两个函数,如果完全匹配,才返回匹配的索引,即:当s中含有abc三个连续的字母时,才返回当前索引。
s.find_first_of(sub), s.find_first_not_of(sub), s.find_last_of(sub), s.find_last_not_of(sub) 这四个函数,查找s中含有sub中任意字母的索引。
如果没有查询到,则返回string::npos,这是一个很大的数,其值不需要知道。
下面是另一种关于此题的解法(非常有意思)
就是把找到的元音换成1,非元音换成零。
举个符合序列的例子:
hhhaaaakkkkiii
这个序列将被转化为:
00011110000111
此种序列一定符合的规律:
- 以0开头1结尾
- 其中变换次数为三次(不能多不能少)
但是怎样将第二条转化为数学语言呢?
对于任意i>=0&s[i]与s[i+1]相加的结果为1,这样的i有三个。
代码如下:
#include
int work();
using namespace std;
int main() {
while (1) { //死循环是为了测试
if (work())
cout << "yes" << endl;
else
cout << "no" << endl;
}
return 0;
}
inline bool isYuan(char c) {
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
int work() {
string word;
getline(cin, word);
unsigned long size = word.size();
if (size < 4)
return 0;
if (isYuan(word[0]) || !isYuan(word[size - 1]))
return 0;
int *h = new int[size];
for (int i = 0; i < size; ++i) {
if (isYuan(word[i]))
h[i]=1;
else
h[i]=0;
}
int cnt=0;
for (int i = 1; i < size; ++i) {
if (h[i-1]+h[i]==1)cnt++;
}
delete[]h;
return cnt==3;
}
需要注意,这里又有一个c++的知识点:
内联函数:
函数的运用可以提高程序的运行效率,但是某些函数反复调用也会影响运行效率,对于某些函数本身很简单,规模小有使用频繁的可以使用内联函数。内联函数不是在调用时发生控制转移而是在编译时将函数体嵌入每一个掉用处,所以不浪费运行时间。特别对蓝桥杯这种限制了时间的竞赛来讲。但是对于复杂的函数使用内联函数,则会使函数膨胀,怎大开销。