蓝桥杯官网练习题

本文提供了一系列编程挑战,包括进制转换、楼梯步数计算、特定数的平方构成等差数列、判断素数截断性以及寻找特定数的二进制特性。这些问题涉及到数学和算法知识,如素数检测、动态规划和位运算。
摘要由CSDN通过智能技术生成

目录

1.进制模拟

2.超级楼梯

3.2019

4.可截断素数

 5.最小数

6.数天数 

7.非常特殊的数

8.最大值路径 

9.拆分质数 

10.文件拷贝 

 11.除去重复单词

12.变成回文字符串 

13.检查拼写错误

14.幸运的3

15.连续的串 

16.找1 

17.排号报数

18.K倍区间


1.进制模拟

 题目描述

小明用字母A对应数字1,字母B对应数字2,...,字母Z对应26,AA对应27,AB对应28,AZ对应52,LQ对应329.

样例输入

样例

A  

#include<bits/stdc++.h>
#include<string>
using namespace std;
char str[27]={0,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','Y','Z'};
int main()
{
    int n;
    cin>>n;
    string x;
    int m;
    while(n>0)
    {
        m=n%26;
        if(m==0) 
        {
            x+='Z';
            n=n/26+1;
        }
        else
        {
            x+=str[m];
            n/=26;
        }
    }
    for(int i=x.size()-1;i>=0;i--)
    {
        cout<<x[i];
    }
    return 0;
}

2.超级楼梯

 

 题目描述

有一个共m级的楼梯,刚开始时你在第一级,每次只能跨上1级或者2级,要走上m级,共有多少种走法。

输入格式

首先包含一个整数N表示测试的组数,然后是N行数据,每行一个整数m. 

样例输入

2

2

样例输出

1

2  

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int m;
        cin>>m;
        int f2=1,f3=2,f=0;
        if(m==1) cout<<0<<endl;
        else if(m==2) cout<<1<<endl;
        else if(m==3) cout<<2<<endl;
        else
        {
            for(int i=4;i<=m;i++)
            {
                f=f2+f3;
                f2=f3;
                f3=f;
            }
            cout<<f<<endl;
        }
    }
    return 0;
}

3.2019

 题目描述

请你找到两个正整数X,Y满足下面条件:

1、N<X<Y

2、N^2、X^2、Y^2构成等差数列

满足条件的X和Y有可能有很多种情况,求X+Y的最小值。对于所有样例,0<N<=2019.

样例输入

2019 

样例输出

7020 

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int N;
    cin>>N;
    for(int X=N+1;;X++)
    {
        int Y=sqrt(2*N*N-N*N);
        if(2*N*N==N*N+Y*Y) //再次带入验证
        {
            cout<<X+Y<<endl;
            return 0;
        }
    }
    return 0;
}

4.可截断素数

 题目描述

左截断素数是不包含0位的素数 ,当连续删除第一个数字时,结果始终为素数。

右截断素数是不包含0为的素数,当连续删除最后一位时,结果始终为素数。

创建一个将整数作为参数的函数,并且:

如果整数只是一个可左截断的素数,则返回“left”。

如果整数只是一个可右截断的素数,则返回“right”。

如果整数是两者,返回“both”。

否则,返回“False”。

样例输入1

9137

样例输出

left 

样例输入2

5939

样例输出

right  

#include<bits/stdc++.h>
#include<vector>
using namespace std;
const int N=1e6+10;
int is_primes(int n)
{
    if(n<=1) return 0;
    for(int i=2;i<=n/i;i++)
        if(n%i==0) return 0;
    return 1;
}

int f1(int n)
{
    vector<int> a;
    int l=n;
    while(n>0)
    {
        a.push_back(n%10);
        n/=10;
    }
    int ans=0,sum=0;
    for(int i=0;i<a.size();i++)
    {
        ans+=a[i]*pow(10,i);
        if(is_primes(ans)) sum++;
    }
    if(sum==a.size()) return 1;
    else return 0;
}

int f2(int n)
{
    int ans=0,sum=0;
    while(n>0)
    {
        if(is_primes(n)) ans++;
        sum++;
        n/=10;
    }
    if(ans==sum) return 1;
    else return 0;
}

int main()
{
    int n;
    cin>>n;
    int x=0,y=0;
    if(f1(n)) x++;
    if(f2(n)) y++;
    if(x==1&&y==0) cout<<"left";
    else if(x==0&&y==1) cout<<"right";
    else if(x==0&&y==0) cout<<"False";
    else if(x==1&&y==1) cout<<"both";
    return 0;
}

 5.最小数

题目描述

请找到一个大于2022的最小数,这个最小的数转换成二进制后,最低的6个二进制全为0.

思路:枚举即可。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

bool check(int n)
{
    vector<int> c;
    while(n)
    {
        c.push_back(n%2);
        n/=2;
    }
    for(int i=0;i<6;i++)
        if(c[i]!=0) return false;
    return true;
}

int main()
{
    for(int i=2023;;i++)
        if(check(i))
        {
            cout<<i;
            return 0;
        }
    return 0;
}

6.数天数 

 问题描述

我们计算从1949年10月1日至2022年1月1日一共经历了多少天?

#include<iostream>
using namespace std;

bool check(int n)
{
    if(n%4==0&&n%100!=0||n%400==0) return true;
    return false;
}

int main()
{
    int res=31+30+31;
    for(int i=1950;i<2022;i++)
    {
        res+=365;
        if(check(i)) res++;
    }
    cout<<res;
    return 0;
}

7.非常特殊的数

题目描述 

8518是一个非常特殊的数,如果把这个数看成16进制,那么他的值为8161616+51616+116+8=3472 ,而34072正好是8518的整数倍。9558也是这样一个数,当看成16进账时是38232.其实长度为1的数0到9都满足看成16进制是自己的整数倍.请问,除开长度为1的数,最小的满足这样条件的数是多少?

思路:从10开始枚举即可。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int main()
{
    for(int i=10;i<=8518;i++)
    {
        string s=to_string(i);
        int len=s.size();
        int sum=0;
        for(int j=0;j<len;j++)
        {
            int t=len-j-1;
            int tmp=1;
            while(t--) tmp*=16;
            sum+=tmp*(s[j]-'0');
        }
        if(sum%i==0)
        {
            cout<<i;
            break;
        }
    }
    return 0;
}

8.最大值路径 

题目描述

小蓝有一个30行60列的数字矩阵,矩阵中每一个数都是0到9之间的数字。现在小蓝想从这个矩阵第一行第一列画一条折线到第30行60列,请问这样经过的折线上的数字之和最大值是多少?

思路:dp问题,f[i][j]中i表示向左走的数字之和,j表示向下走的数字之和,w[i][j]:表示i行j列上面的数字 。

最后一格不是从上面到最后一格,就是从左边到最后一格。

 

f[i][j]表示的集合如下:

则状态转移方程f[i][j]=max(f[i-1][j],f[i][j-1])+w[i][j], 

代码如下: 

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100;
int w[N][N],f[N][N];
int main()
{
    for(int i=1;i<=30;i++)
    {
        string s;
        cin>>s;
        for(int j=1;j<=60;j++) w[i][j]=s[i-1]-'0';
    }
    f[1][1]=w[1][1];
    for(int i=1;i<=30;i++)
        for(int j=1;j<=60;j++)
        {
            if(i==1&&j==1) continue;
            f[i][j]=max(f[i-1][j],f[i][j-1])+w[i][j];
        }
    cout<<f[30][60]<<endl;
    return 0;
}

9.拆分质数 

题目描述

将2022拆分成不同的质数的和,请问最多可以拆分几个? 

思路:01背包的变形,可以先求出0~2022之间所有的质数,假设这些质数就是物品,背包的容量就是2022,只要找出最多可以放进背包的物品个数,就可以解决。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

const int N=3000;
int q[N];
int f[N][N];
int v[N];
int n=1;

bool check(int n)
{
    for(int i=2;i<=n/i;i++)
        if(n%i==0) return false;
    return true;
}

int main()
{
    for(int i=2;i<=2022;i++)
        if(check(i)) v[n++]=i;
    int m=2022;
    for(int i=1;i<n;i++)
        for(int j=2;j<=m;j++)
            if(v[i]>j) f[i][j]=f[i-1][j];
            else f[i][j]=max(f[i-1][j],f[i][j-v[i]]+1);
    cout<<f[n-1][m];
    return 0;
}

10.文件拷贝 

题目描述

小蓝正在拷贝一件文件,他现在已经拷贝了t秒时间,已经拷贝了c字节,文件总共有s字节,如果拷贝是匀速进行的,请问小蓝大概还要拷贝多少秒?

输入格式 

输入一行包含3个整数t,c,.

输出格式 

输出一个整数表示答案。

数据范围 

1<=t,c,s<=1000000000.

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;

int main()
{
    ll t,c,s;
    cin>>t>>c>>s;
    double v=t*1.0/c;
    s-=c;
    double cnt=s*v;
    if(cnt-(int)cnt>0) cout<<(int)cnt+1<<endl;
    else cout<<(int)cnt<<endl;
    return 0;
}

 11.除去重复单词

问题描述

小蓝有n个单词,但是有些单词是重复的,请你去掉重复的单词。

样例输入:

5

apple

apple 

net 

think

net

样例输出

think 

数据范围

1<=n<=100 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_map>
#include<vector>
using namespace std;
unordered_map<string,int> h;
vector<string> c;
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        string x;
        cin>>x;
        if(h.count(x)==1) continue; //已经出现过
        else
        {
            c.push_back(x);
            h[x]++;
        }
    }
    for(int i=0;i<c.size();i++)
        cout<<c[i]<<endl;
    return 0;
}

12.变成回文字符串 

 题目描述

一个字符串如果从左往右和从右往左读相同,则称为回文串,例如lanqiaoaiqnal是一个回文串。小蓝有一个字符串,请你在这个字符串的右边加入若干字符,使其成为一个回文串,请你输出最短的回文串。

数据范围

1<=字符串长度<=100 

思路:从头往后遍历,找到第一个元素,以这个元素为起点到字符串末尾 构成一个回文串,此时这段区间就是公共的区间,只需要把这个字符前面的字符串反转到末尾即可。

这时候我们需要用到反转函数和字符串中i到j之间的字符串的函数,我们可以先考虑stl库,如果实在想不到,可以手写。

substr函数:

string substr(string x,int i,int j)
{
    string y;
    for(int k=i;k<=j;k++)
        y+=x[i];
    return y;
}

reverse函数:

string reverse(string x,int i,int j)
{
    string y;
    for(int k=j;k>=i;k--)
        y+=x[i];
    return y;
}
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

string s;

bool check(string s)
{
    int l=0,r=s.size()-1;
    while(l<r)
    {
        if(s[l++]!=s[r--]) return false;
    }
    return true;
}

int main()
{
    cin>>s;
    int i=0;
    int n=s.size();
    for(i=0;i<n;i++)
    {
        string x=s.substr(i,n); //把[i,n)之间的字符拼接起来构成一个字符串
        if(check(x)) break;
    }
    string t=s.substr(0,i);
    reverse(s.begin(),s.end());
    cout<<s+t;
    return 0;
}

13.检查拼写错误

 题目描述

给出一些单词,然后拼写一些单词,检查的单词是否有拼写错误。统计错误的个数。

样例输入

5

apple

be

love

up

down

3

up

down

bee 

样例输出

开一个set哈希,检查单词的个数在set中是否出现过。

#include<iostream>
#include<set>
using namespace std;
int main()
{
    set<string> mp;
    int t,n;
    cin>>t;
    while(t--)
    {
        string x;
        cin>>x;
        mp.insert(x);
    }
    int ans=0;
    cin>>n;
    while(n--)
    {
        string x;
        cin>>x;
        if(mp.count(x)==0) ans++;
    }
    cout<<ans<<endl;
    return 0;
}

14.幸运的3

题目描述

你有n个数,可以将题目两两匹配(即两个数首尾相连),每个数只能使用一次,问匹配后最多有多少个3的倍数?

输入格式

第一行一个n,接下来n个正整数。 

输出格式

输出最多有多少3的倍数。 

样例输入

123 123 99 

样例输出

思路:如果两个数都能够整除3,拼出来的数字那么一定 可以整除3,一个余数为2和余数为1的数也可以拼出能够整除3的数。

#include<iostream>
using namespace std;
int a[4];
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int x;
        cin>>x;
        a[x%3]++;
    }
    cout<<a[3]/2+min(a[1],a[2]);
    return 0;
}

15.连续的串 

题目描述

给你一个字符串,找出次数最多的长度为2的子串。

输入格式:

第一行为一个正整数n,表示给出字符串的长度,第二行为字符串。 

输出格式:

输出所求的字符串,若有多个结果,输出字典序最小的。 

样例输入: 

7

ABACABA

样例输出:

AB 

数据范围

2<=n<=100 

思路:简单哈希。 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
const int N=110;
char x[N];
map<string,int> h;
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>x[i];
    for(int i=1;i<=n-1;i++)
    {
        string y="";
        y+=x[i];
        y+=x[i+1];
        h[y]++;
    }
    int ans=0;
    string res;
    for(map<string,int>::iterator it=h.begin();it!=h.end();it++)
    {
        if(it->second>ans)
        {
            ans=it->second;
            res=it->first;
        }
        else if(it->second==ans)
              res=min(res,it->first);
    }
    cout<<res<<endl;
    return 0;
}

16.找1 

题目描述

最近小码哥爱上了二进制,他特别喜欢全是1的二进制,但通常会有0.

于是他给你一个二进制字符串,问你字符都为1的字串的个数(结果对109+7取模)

输入格式:

一个二进制字符串 

输出格式:

所有字符串都为1子串的个数。 

样例输入1:

0110111

样例输出1:

9

样例输入2:

101

样例输出2:

2

样例输入3:

111111

样例输出3: 

21

数据范围

1<=s.length<=1e5 

思路:我们用双指针算法,我们用sum记录总数,每次最多连续1的长度ans,则每次的方案数为 1+2+...+ans,我们这时候可以有两种方法:

方法一:直接暴力

for(int j=1;j<=ans;j++) ans+=j;

sum+=ans;

方法二:公式优化

1+2+..+n=n*(n+1)/2.

sum+=ans*(ans+1)/2;

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
    string s;
    cin>>s;
    int sum=0;
    for(int i=s.size()-1;i>=0;i--)
    {
        int ans=0;
        int j=i;
        while(s[j]=='1'&&j>=0)
        {
            ans++;
            j--;
        }
        sum+=ans*(ans+1)/2;
        i=j;
    }
    cout<<sum;
    return 0;
}

17.排号报数

 题目描述

有N个人绕成一个圈,按照顺序开始报数(1-N),第一个人从1开始依次报数,报到3的人淘汰,接下来的人又从1依次开始报数,报到3的人淘汰,直到只剩下最后一个人,问最后留下了的是原来第几号的那个人。

样例输入

10 

样例输出

规律:

int f(int n,int m)
{
    int x=0;
    for(int i=2;i<=n;i++)
        x=(x+m)%i;
    return x+1;//如果从第q个人开始报数,返回x+q;
}
#include<bits/stdc++.h>
using namespace std;
int f(int n,int m)
{
    int x=0;
    for(int i=2;i<=n;i++)
        x=(x+m)%i;
    return x+1;
}
int main()
{
    int n;
    cin>>n;
    cout<<f(n,3);
    return 0;
}

18.K倍区间

 题目描述

给定一个长度为N的数列,A1,A2,...,AN,如果其中一段连续的子序列之和是k的倍数,就说是k倍区间,现在给你一个序列,请问你有多少个k倍区间。

样例输入

5 2

1

2

3

4

样例输出

#include<iostream>
using namespace std;

typedef long long LL;
const int N=100010;

int n,k;
LL ans;
LL a[N],s[N],cnt[N];

int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        s[i]=s[i-1]+a[i];
    }
    cnt[0]=1;
    for(int i=1;i<=n;i++)
    {
        ans+=cnt[s[i]%k]++;
    }
    cout<<ans;
    return 0;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值