蓝桥杯刷题-入门题(终章一)

你是如风的少年~

空 清新民谣版 - 汪小敏 - 单曲 - 网易云音乐

自在的少年 - 要不要买菜 - 单曲 - 网易云音乐

最后15道入门题,做完这15道,NEWOJ就91道题AC了

目录

一,数根

二,最大值和最小值(I)

三,打印直角三角形

四,最大值和最小值(II)

五,消消乐(一题多解)

字符串操作函数 

代码1  s.substr(i, j)

代码2  s.erase(i , j) 

代码3   栈

六,按纯度筛选(超限!!)

七,加密数(溢出!!)

总结 


一,数根

P1062 - 数根 - New Online Judge (ecustacm.cn)

蓝桥杯刷题-入门题(终章一)_第1张图片 

卡了好久...思路真的很简单,20行代码的事

1,按字符串输入,转整型

2,整型不用转回字符串再转整型了(麻烦,而且不好实现)(这步想复杂了...)

     类似十进制转八进制那样,直接取每一位相加,如果依旧>= 10(即 / 10 != 0),重复这一步

 3,注意,构造函数中的return需要赋值给一个变量,而cout才能直接输出

#include
using namespace std;
int number(int x)
{
    int y = 0;
    while(x) { //注意是x!= 0
        y += x % 10;
        x /= 10;
    }
    if(y / 10 == 0) cout<>s;
    for(int i = 0; i < s.size(); ++i)
        a += s[i] - '0';
    number(a);
    return 0;
}
24
6

6666
6

9127812749871298471928748124781278471827489214
7

二,最大值和最小值(I)

P1063 - 最大值和最小值(I) - New Online Judge (ecustacm.cn)

蓝桥杯刷题-入门题(终章一)_第2张图片 

输入a[n],对a[n]排序得到b[n],b[0]和b[n - 1]即最小值和最大值再通过遍历将 i 赋值给数组,c[a[i]] = i得到元素对应的下标需要注意的是,遍历到最大值b[n - 1]即可)然后c[b[0]] - c[b[n - 1]]相减取abs

 第一次提交,Ac 90%,因为没考虑比如1 1 1 1的情况,按原代码会输出-1,需要加个max(0, ...)

通过代码

#include
#include //abs
#include //sort()
using namespace std;
int a[10010], b[10010], c[10010];;
int main()
{
    int ans, n;
    cin>>n;
    for(int i = 0; i < n; ++i) {
        cin>>a[i];
        b[i] = a[i];
    }
    sort(b, b + n); //从小到大
    for(int i = 0; i <= b[n - 1]; ++i) c[a[i]] = i;//元素对应下标
    ans = abs(c[b[0]] - c[b[n - 1]]) - 1;
    cout<

三,打印直角三角形

P1064 - 打印直角三角形 - New Online Judge (ecustacm.cn)

蓝桥杯刷题-入门题(终章一)_第3张图片 

#include
using namespace std;
int main()
{
    int n;
    while(cin>>n) {
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= i; ++j)
                cout<<"*";
            cout<

注意,图形用空行分开 

四,最大值和最小值(II)

P1065 - 最大值和最小值(II) - New Online Judge (ecustacm.cn)

蓝桥杯刷题-入门题(终章一)_第4张图片 

一开始排序写成sort(a, a + n).....所以Ac 20%,改成sort(a, a + 3)就好了

#include
#include //sort()
#include //memset()
using namespace std;
int a[4]; //保存每只队伍分数
int main()
{
    int n, ans = 10000, num;
    cin>>n;
    for(int i = 1; i <= n; ++i) {
        memset(a, 0, sizeof(a)); //每只队伍都要更新a
        for(int j = 0; j < 3; ++j) {
            cin>>a[j];
        }
        sort(a, a + 3);
        if(ans > a[2] - a[0]) {
            ans = min(ans, a[2] - a[0]);
            num = i;
        }
    }
    cout<

虽说memset速度慢,但是只有三个数据的话,每次更新一下不影响

五,消消乐(一题多解)

给大家展示下一题多解 

题目 

P1066 - 消消乐 - New Online Judge (ecustacm.cn)

蓝桥杯刷题-入门题(终章一)_第5张图片 蓝桥杯刷题-入门题(终章一)_第6张图片

解析 

1,s.substr(i)下标 i 开始到结尾,s.substr(i, j)从下标 i 开始截取 j 个字符(代码1)

2,其实用删除函数更好(代码2)

3,当然用也可以(代码3)

第一次发现个小问题,用s.substr()写了删除函数后,发现全局变量在构造函数被修改后,主函数中并没有被改变,苦苦思索了半小时发现,忘记return了......↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

#include
#include //substr()
using namespace std;
string s;

void cut(string s) //消去一次
{
    int r = 0;
    for(int i = 1; i < s.size(); ++i) {
        if(s[i] == s[i - 1]) r++;
        else r = 0;
        if(r == 2) {
            s = s.substr(0, i - 2) + s.substr(i + 1);
            cout<<"函数中全局变量被修改了:"<>s;
    cut(s);
    cout<<"主函数中输出不变:"<
aaaabbbc
函数中全局变量被修改了:abbbc
主函数中输出不变:aaaabbbc

忘记return浪费半小时 

改成这样即可

#include
#include //substr()
using namespace std;
string s;

string cut(string s) //这里要加*, 否则主函数中不变
{
    int r = 0;
    for(int i = 1; i < s.size(); ++i) {
        if(s[i] == s[i - 1]) r++;
        else r = 0;
        if(r == 2) {
            s = s.substr(0, i - 2) + s.substr(i + 1);
            cout<<"函数中全局变量被修改了:"<>s;
    s = cut(s);
    cout<<"主函数中输出不变:"<
aaaabbbc
函数中全局变量被修改了:abbbc
主函数中输出不变:abbbc

首先声明函数时,要声明为string;其次,函数中修改s后,必须return; 最后,主函数中函数的return要赋值给一个变(大坑

字符串操作函数 

1,截取子串

s.substr(i)下标 i 开始到结尾,s.substr(i, j)从下标 i 开始截取 j 个字符

2,替换子串

s.replace(i, j, s1)用s1替换s中从下标 i 开始的 j 个字符

3,查找子串

s.find(s1)查找s1在s第一次出现的下标

s.rfind(s1)查找s1在s最后一次出现的下标

4,删除子串

s.erase(i, j)删除从下标 i 开始的 j 个字符 

代码1  s.substr(i, j)

#include
#include //substr()
using namespace std;
string s;
int flag = 1;
string cut(string s)
{
    flag = 0;
    int r = 0;
    for(int i = 1; i < s.size(); ++i) {
        if(s[i] == s[i - 1]) r++;
        else r = 0;
        if(r == 2) {
            flag = 1; //可能还存在3个连续的
            s = s.substr(0, i - 2) + s.substr(i + 1);
            return s;
            break;
        }
    }
    return s; //最后一步return s; 别漏了
}
int main()
{
    cin>>s;
    while(flag) {
        s = cut(s);
    }
    cout<

1,代码第15行,i - 2 和 i + 1 的规律,可以自己在草稿纸罗列acbbbab对应着下标0~6试试

2,cut()函数结尾的return s; 也是个坑

代码2  s.erase(i , j) 

#include
//#include
using namespace std;
string s;
int flag = 1;
string cut(string s)
{
    flag = 0;
    int r = 0;
    for(int i = 1; i < s.size(); ++i) {
        if(s[i] == s[i - 1]) r++;
        else r = 0;
        if(r == 2) {
            flag = 1; //可能还存在3个连续的
            s.erase(i - 2, 3); //从i - 2开始,删除3个
            return s;
            break;
        }
    }
    return s; //最后一步return s; 别漏了
}
int main()
{
    cin>>s;
    while(flag) {
        s = cut(s);
    }
    cout<

 也就把代码1第15行换成了      s.erase(i - 2, 3);

代码3   栈

s.pop()仅删除栈顶元素,不返回元素,返回void;而s.top()返回栈顶元素,不删除;

s.push()将元素入栈

C++ STL 之stack_buyizhu021的博客-CSDN博客_stack赋值

 

经过对stack的学习(半小时),再耗费半小时,,还是没完全靠自己敲出来,抄吧

抄着抄着就会了

#include
#include //st.pop(), st.push()
#include //reverse()
using namespace std;
string s;

string cut(string s) //声明全局就别传参了
{
    stackst; //记住这种格式
    for(int i = 0; i < s.size(); ++i) {
        if(st.size() >= 2) { //此处'>'不可少,否则只消去一次
            //获取两个元素的值
            int a = st.top(); //第一个
            st.pop(); //第一个出栈
            int b = st.top(); //第二个
            st.push(a); //恢复原样
            if(s[i] == a && a == b) {//3个元素一样
                st.pop();
                st.pop();
            }
            else st.push(s[i]); //不一样就把第三个也入栈
        }
        else st.push(s[i]); //栈里元素不足2个
    }
    s = ""; //初始化s为空串
    while(!st.empty()) {
        s += st.top();
        st.pop();
    } //栈后进先出,所以字符串反转
    reverse(s.begin(), s.end());
    return s;
}
int main()
{
    cin>>s;
    s = cut(s);
    cout<

六,按纯度筛选(超限!!)

P1067 - 按纯度筛选 - New Online Judge (ecustacm.cn)

蓝桥杯刷题-入门题(终章一)_第7张图片 蓝桥杯刷题-入门题(终章一)_第8张图片

1,第一次报错error: can not convert ... to const char*,因为我strcmp来比较string类的字符串,把string类改成char就好

2,结构体是变量的集合体,切记

3,第二次发现,写的统计字母种类的函数ki()没起作用,原来是数组a[]没有初始化,连0都没有何来++,a[26]改成a[26] = {0},而且设置26为长度的话,遍历时下标要从0开始,否则超限也会输出错误答案 

4,第三次!测试样例 + 自己编的包含所有情况的七八组数据,都没问题,但是提交就答案错误。。。what's wrong...

5, 发现问题了,第13行26个桶设置成a[26]会超限,导致你这里结果对,但是系统不给你过,a[26] ----> a[30]AC

AC代码

#include
#include //strcmp(),比较字典序;strlen()
#include //sort()
using namespace std;
struct stone
{
    int len, kind; //长度和种类
    char ss[110];
}s[110];

int ki(char s[]) //得到纯度
{
    int kind = 0, a[30] = {0}; //a[30]表示26个桶,设置30防止超限
    for(int i = 0; i < strlen(s); ++i)
        if(a[s[i] - 'a' + 1] == 0) {
            a[s[i] - 'a' + 1] = 1;
            kind++;
        }
    return kind;
}

bool cmp(stone x, stone y) //三种比较规则
{
    if(x.kind != y.kind)
        return x.kind < y.kind; //返回纯度高的
    else if(x.len != y.len)
        return x.len > y.len; //返回长度大的
    else //如果纯度长度都相等
        return strcmp(x.ss, y.ss) < 0; //返回字典序小的
}

int main()
{
    int n;
    while(cin>>n) {
        if(n == 0) break;
        for(int i = 0; i < n; ++i) {
            cin>>s[i].ss;
            s[i].kind = ki(s[i].ss);
            s[i].len = strlen(s[i].ss);
        }
        sort(s, s + n, cmp);
        for(int i = 0; i < n; ++i) {
            cout<

七,加密数(溢出!!)

P1068 - 加密数 - New Online Judge (ecustacm.cn)

蓝桥杯刷题-入门题(终章一)_第9张图片蓝桥杯刷题-入门题(终章一)_第10张图片

要做出这题,首先要了解十进制的二进制表示方法,其次是原码反码补码 

(6条消息) 原码、反码、补码详解_独在黑夜_看湖面的博客-CSDN博客_原码反码补码

首先,经过计算 2^7 + 2^8 + 2^16 == 65920,

每8位作为一个整体,130 = 0 + 2^0 + 2^0 + 2^7

负数的二进制在计算机中表示为补码,即原码基础上,除符号位外取反+ 1

-1

原码为10000000 00000000 00000000 00000001

反码为11111111 11111111 11111111 11111110

补码(也就是计算机中形式)11111111 11111111 11111111 11111111

所以-1的加密数为 (1+2+4+8+16+32+64+128) * 4 = 1020

我们要做的是,写个将负数转换为补码的函数(详细步骤看代码注释) 

害,整了20个从0到10^9+的数据,包括10个对应负数,跑对拍都没问题。。是系统的问题?

找到原因了!!第5行int c要改long long,因为传入时确实在 int 范围内,但是函数中操作时,可能会取反,比如2^31的二进制取反,由于是无符号整型,会超出int范围(溢出

Ac代码 

#include
#include //memset()
using namespace std;
int a[100];
void binary(long long c, int b[])
{
    int flag = 0;
    if(c < 0) {
        c = -c;
        flag = 1;
    }
    for(int i = 0; i < 32; ++i) { //转二进制
        b[i] = c % 2;
        c /= 2; //最低位存入数组第一位
    }
    if(flag) {
        for(int i = 0; i < 32; ++i) { //取反,变反码
            if(b[i] == 0) b[i] = 1;
            else if(b[i] == 1) b[i] = 0;
        }
        for(int i = 0; i < 32; ++i) { //加1, 变补码
            if(b[i] == 0) {b[i] = 1; break;}
            else b[i] = 0;
        }
    }
}
int main()
{
    int n;
    while(cin>>n) {
        memset(a, 0, sizeof(a)); //初始化数组
        int ans = 0;
        binary(n, a);
        int pro = 1;
        for(int i = 0; i < 32; ++i) { //计算答案
            if(i % 8 == 0) pro = 1; //每8位作为整体
            if(a[i] == 1) ans += pro;
            pro *= 2;
        }
        cout<

总结 

1,加深了对函数传参return全局变量的了解

2,初步学习了用特例推翻代码,并重构的方法

3,学会跳出思维定势,比如sort(a, a + n)也可能是sort(a + 1, a + n + 1),sort(a, a + 3)......

4,初步学习并运用s.substr(i, j), s.erase(i, j)解决问题(头文件#include

      并通过一题多解锻炼解题能力

5,数组超限!老生常谈了,每次最好多设10个长度,多设死不了,少了一定不行

6,int溢出的问题,但这次是初始没溢出,后续操作导致数据超过2^31才溢出的,大坑 

你可能感兴趣的:(2024蓝桥杯备赛,蓝桥杯)