蓝桥杯 历届真题

蓝桥杯------历届真题

《1》核桃的数量  

问题描述

小张是软件项目经理,他带领3个开发组。工期紧,今天都在加班呢。为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑)。他的要求是:

1. 各组的核桃数量必须相同

2. 各组内必须能平分核桃(当然是不能打碎的)

3. 尽量提供满足1,2条件的最小数量(节约闹革命嘛)

输入格式
输入包含三个正整数a, b, c,表示每个组正在加班的人数,用空格分开(a,b,c<30)
输出格式
输出一个正整数,表示每袋核桃的数量。
样例输入1
2 4 5
样例输出1
20
样例输入2
3 1 1
样例输出2
3
 题目解析
  其实题目就是要求a,b,c的最小公倍数。
参考代码
#include<stdio.h>

int f(int a,int b)
{
    int i,t;
    if(b>a)
    {
        t=a;
        a=b;
        b=t;
    }
    for(i=a;;i=i+a)
    {
        if(i%a==0&&i%b==0)break;
    }
    return i;
}

int main()
{
    int a,b,c,r;
    
    scanf("%d%d%d",&a,&b,&c);
    
    r=f(a,b);
    r=f(r,c);
    
    printf("%d
",r);
    
    return 0;
}

《2》打印十字图  

问题描述

小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示:

..$$$$$$$$$$$$$..
..$...........$..
$$$.$$$$$$$$$.$$$
$...$.......$...$
$.$$$.$$$$$.$$$.$
$.$...$...$...$.$
$.$.$$$.$.$$$.$.$
$.$.$...$...$.$.$
$.$.$.$$$$$.$.$.$
$.$.$...$...$.$.$
$.$.$$$.$.$$$.$.$
$.$...$...$...$.$
$.$$$.$$$$$.$$$.$
$...$.......$...$
$$$.$$$$$$$$$.$$$
..$...........$..
..$$$$$$$$$$$$$..

对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。

输入格式
一个正整数 n (n<30) 表示要求打印图形的层数。
输出格式
对应包围层数的该标志。
样例输入1
1
样例输出1
..$$$$$..
..$...$..
$$$.$.$$$
$...$...$
$.$$$$$.$
$...$...$
$$$.$.$$$
..$...$..
..$$$$$..
样例输入2
3
样例输出2
..$$$$$$$$$$$$$..
..$...........$..
$$$.$$$$$$$$$.$$$
$...$.......$...$
$.$$$.$$$$$.$$$.$
$.$...$...$...$.$
$.$.$$$.$.$$$.$.$
$.$.$...$...$.$.$
$.$.$.$$$$$.$.$.$
$.$.$...$...$.$.$
$.$.$$$.$.$$$.$.$
$.$...$...$...$.$
$.$$$.$$$$$.$$$.$
$...$.......$...$
$$$.$$$$$$$$$.$$$
..$...........$..
..$$$$$$$$$$$$$..
提示
请仔细观察样例,尤其要注意句点的数量和输出位置。
参考代码
#include<stdio.h>

char a[10000][10000];

int main()
{
    int n,i,j,k,b,r,c,d,t,m;
    scanf("%d",&n);
    
    int row=9+(n-1)*4,cll=row,mid=row/2+1;
    k=n-1;
    for(i=1;i<=row/2;k--)
    {
        m=5+4*k;
        b=(row-m)/2;
    //    if(i%2==1)
    //    {
            a[i][mid]='$';
            for(r=mid+1;r<=row-b;r++)
            {
                a[i][r]=a[i][row-r+1]='$';
            }
            if(b==2)
            {
                a[i][r]=a[i][row-r+1]='.';r++;
                a[i][r]=a[i][row-r+1]='.';r++;
            }
            else
            {
                a[i][r]=a[i][row-r+1]='.';r++;t=r+2;
                for(;r<=t;r++)a[i][r]=a[i][row-r+1]='$';
                for(;r<=row;)
                {
                    a[i][r]=a[i][row-r+1]='.';r++;
                    a[i][r]=a[i][row-r+1]='$';r++;
                }
            }
            i++;
    //    }
    //    else
    //    {
            c=m-2;d=(cll-c)/2;
            if(m==1)
            {
                a[i][mid]='$';r=mid+1;
            }
            else
            {
                a[i][mid]='.';
                for(r=mid+1;r<=row-d;r++)    a[i][r]=a[i][row-r+1]='.';
                a[i][r]=a[i][row-r+1]='$';r++;
            }
            //if(d-1==2)
        //    {
                a[i][r]=a[i][row-r+1]='.';r++;
                a[i][r]=a[i][row-r+1]='.';r++;
        //    }
            
            for(;r<=row;)
            {
                a[i][r]=a[i][row-r+1]='.';r++;
                a[i][r]=a[i][row-r+1]='$';r++;
            }
            
    //    }
    i++;
    }
    
    a[i][mid]='$';
    for(r=mid+1;r<=mid+2;r++)a[i][r]=a[i][row-r+1]='$';
    for(;r<=row;)
    {
        a[i][r]=a[i][row-r+1]='.';r++;
        a[i][r]=a[i][row-r+1]='$';r++;
    }
    
    
    for(i=1;i<=row/2+1;i++)
    {
        for(j=1;j<=cll;j++)
        {
            printf("%c",a[i][j]);
        }
        printf("
");
    }
    
    for(i=row/2;i>0;i--)
    {
        for(j=1;j<=cll;j++)
        {
            printf("%c",a[i][j]);
        }
        printf("
");
    }
    
    return 0;
}

《3》 带分数  

问题描述

100 可以表示为带分数的形式:100 = 3 + 69258 / 714。

还可以表示为:100 = 82 + 3546 / 197。

注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。

类似这样的带分数,100 有 11 种表示法。

输入格式

从标准输入读入一个正整数N (N<1000*1000)

输出格式

程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。

注意:不要求输出每个表示,只统计有多少表示法!

样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6
参考代码
/*
问题描述
    100 可以表示为带分数的形式:100 = 3 + 69258 / 714。
    还可以表示为:100 = 82 + 3546 / 197。
    注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
    类似这样的带分数,100 有 11 种表示法。
输入格式
    从标准输入读入一个正整数N (N<1000*1000)
输出格式
    程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
    注意:不要求输出每个表示,只统计有多少表示法!
样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6
*/

#include<stdio.h>
#include<string.h>
#include<math.h>

#define M 9

int back[M+1],flag[M+1],sum;

//求常数项的标志
int f1(int a) { int i,j=0; memset(flag,0,sizeof(flag)); while(a) { j++; i=a%10; if(i==0 || flag[i]==1)return 0; else flag[i]=1; a/=10; } return j; }
//求分子或分母是否符合要求
int f2(int a) { memcpy(back,flag,sizeof(flag)); int i,j=0; while(a) { j++; i=a%10; if(i==0 || back[i]==1)return 0; else back[i]=1; a/=10; } return j; }
//求分子a和分母b是否满足要求
int f3(int a,int b) { memcpy(back,flag,sizeof(flag)); int i; while(a) { i=a%10; if(i==0 || back[i]==1)return 0; else back[i]=1; a/=10; } while(b) { i=b%10; if(i==0 || back[i]==1)return 0; else back[i]=1; b/=10; } for(i=1;i<=M;i++) { if(back[i]==0)return 0; } return 1; } int main() { int N,i,j,k,nz,nfz,nfm,a,b,fz,fm,fzup; scanf("%d",&N); sum=0; for(i=1;i<=N;i++) { if((nz=f1(i))==0)continue; fzup=pow(10,M-nz+1)-1; a=N-i;b=1; for(k=2;k<=98765&&a*k<fzup;k++) { if((nfz=f2(k))==0)continue; if(f3(a*k,k)==1) { sum++; // printf("zshu=%d fz=%d fm=%d ",i,a*k,k); } } } printf("%d ",sum); return 0; }

《4》剪格子  

问题描述

如下图所示,3 x 3 的格子中填写了一些整数。

+--*--+--+
|10* 1|52|
+--****--+
|20|30* 1|
*******--+
| 1| 2| 3|
+--+--+--+

我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60。

本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。

如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。

如果无法分割,则输出 0。

输入格式

程序先读入两个整数 m n 用空格分割 (m,n<10)。

表示表格的宽度和高度。

接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000。

输出格式
输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。
样例输入1
3 3
10 1 52
20 30 1
1 2 3
样例输出1
3
样例输入2
4 3
1 1 1 1
1 30 80 2
1 1 1 100
样例输出2
10
题目分析
  显然这里要用到搜索算法,而这样的算法常常借助于方向数组来完成
参考代码
#include<stdio.h>
#include<string.h>

int xy[][2]={{1,0},{0,1},{-1,0},{0,-1}};//下一步方向{x,y} 
int a[11][11],vis[11][11],sum,m,n;//m列n行 

//检查{x,y}是否可行 
int chack(int x,int y,int num)
{
    if(x<1 ||x>n || y<1 || y>m)
        return 0;
    if((num+a[x][y])>sum)
        return 0;
    if(vis[x][y])
        return 0;
    return 1;
}


int f1(int x,int y,int num)//遍历 
{
    if(num==sum)return 1;
    int i,res=0,xn,yn;
    for(i=0;i<4;i++)//尝试四个方向
    {
        xn=x+xy[i][0];
        yn=y+xy[i][1];
        if(chack(xn,yn,num))
        {
            vis[xn][yn]=1;
            int res=f1(xn,yn,num+a[xn][yn]);
            if(res>0)return res+1;
            vis[xn][yn]=0;
        }
    }
    return 0;
}


int main()
{
    scanf("%d%d",&m,&n);
    int i,j;
    sum = 0;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            sum+=a[i][j];
        }
    }
    
    if(sum%2==1) printf("0
");//如果所有格子的和不能分成相等的半 
    else
    {
        sum/=2;
        memset(vis,0,sizeof(vis));//从左上角开始遍历 
        vis[1][1]=1;
        printf("%d
",f1(1,1,a[1][1]));
    }
    
    return 0;
}

《5》 翻硬币  

问题描述

小明正在玩一个“翻硬币”的游戏。

桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。

比如,可能情形是:**oo***oooo

如果同时翻转左边的两个硬币,则变为:oooo***oooo

现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?

我们约定:把翻动相邻的两个硬币叫做一步操作,那么要求:

输入格式

两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000

输出格式

一个整数,表示最小操作步数。

样例输入1
**********
o****o****
样例输出1
5
样例输入2
*o**o***o***
*o***o**o***
样例输出2
1
思路
检查两个字符串,若对应位置相等则不翻转,否在将该位置的硬币和下一个相邻位置硬币同时做翻转,依次检查直到检查完毕。

总结:注意:

在测试代码的时候用本地文件存储数据然后读取数据是较快的测试方法,但是要注意再提交代码的时候要将相应的对文件进行操作的代码注释掉
否在提交代码会因找不到相应的文件而报错

参考代码

#include<stdio.h>
#include<string.h>
#define M 10100

char ch1[M],ch2[M]; 
int main()
{
    int i,j,len,step;
    FILE *f;
//    f=fopen("testnum.txt","r+");
//    fscanf(f,"%s
",&ch1);
    scanf("%s
",&ch1);
    //getchar();
//    fscanf(f,"%s",&ch2);
    scanf("%s",&ch2);
    
    len=strlen(ch1);
    step=0;
    char c;
    for(i=0;i<len;i++)
    {
        if(ch1[i]==ch2[i])continue;
        if(ch1[i]=='*')ch1[i]='o';
        else ch1[i]='*';
        if(ch1[i+1]=='*')ch1[i+1]='o';
        else ch1[i+1]='*';
        step++;
    }
    
    printf("%d
",step);
//    fclose(f);
    return 0;
}
https://github.com/hfl15
原文地址:https://www.cnblogs.com/fanling999/p/3607420.html