首页 > 技术文章 > 第五届蓝桥杯总结

douzujun 2018-03-21 23:56 原文

第一题  啤酒和饮料

啤酒每罐2.3元,饮料每罐1.9元。小明买了若干啤酒和饮料,一共花了82.3元。

我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐啤酒。

注意:答案是一个整数。请通过浏览器提交答案。

不要书写任何多余的内容(例如:写了饮料的数量,添加说明文字等)。
#include <iostream>
using namespace std;

int main()
{
    for (int i = 0; i <= 41; i++)
    {
        for (int j = i + 1; j <= 80; j++)
        {
            double ans = 2.3*i + 1.9*j;
            if (ans == 82.3)
            {
                cout << i << " " << j << " " << ans << endl;
                break;
            }
        }
    }
    return 0;
}

答案:11

第二题:切面条

 一根高筋拉面,中间切一刀,可以得到2根面条。

    如果先对折1次,中间切一刀,可以得到3根面条。

    如果连续对折2次,中间切一刀,可以得到5根面条。

    那么,连续对折10次,中间切一刀,会得到多少面条呢?

答案是个整数,请通过浏览器提交答案。不要填写任何多余的内容。

题解:找规律

#include <iostream>
using namespace std;

void solve()
{
    int s = 2;
    
    int ans = s;
    int N;
    cin >> N;
    // 0 : 2
    // 1 : 2*2 - 1 = 3
    // 2 : 2*3 - 1 = 5  
    for (int i = 1; i <= N; i++)
    {
        ans = s * 2 - 1;
        s = ans;
    }
    cout << ans << endl;
}

int main()
{
    solve();
    
    return 0;
}

第三题:李白打酒

话说大诗人李白,一生好饮。幸好他从不开车。

    一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:

    无事街上走,提壶去打酒。
    逢店加一倍,遇花喝一斗。

    这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。 


    请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。

像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。

 

题解:递归.....一定要注意递归结束条件.........店为0,花为0,酒为0,且!最后一个遇到的应该是花,也就是 b。递归的时候也要判断条件。

#include <iostream>
#include <string>
using namespace std;

int ans; 
int N = 2;

void dfs(int dian, int hua, string s, int n)
{
    if (!n && !hua && !dian && s[14] == 'b')
    {
        cout << s << endl;
        ans++;
        return;
    }
    
    if (dian > 0) {
        dfs(dian - 1, hua, s+"a", n*2);
    }
    
    if (hua > 0 && n > 0) {
        dfs(dian, hua - 1, s+"b", n-1);    
    }
    
}

void solve()
{
    dfs(5, 10, "", N);
    cout << ans << endl; 
}

int main()
{
    solve();
    
    return 0;
}

答案:14

 第四题:史丰收运算

史丰收速算法的革命性贡献是:从高位算起,预测进位。不需要九九表,彻底颠覆了传统手算!
速算的核心基础是:
1位数乘以多位数的乘法。其中,乘以7是最复杂的,
就以它为例。
因为,1/7 是个循环小数:0.142857...,如果多位数超过 142857...,就要进1
同理,2/7, 3/7, ... 6/7 也都是类似的循环小数,多位数超过 n/7就要进n
下面的程序模拟了史丰收速算法中乘以7的运算过程。
乘以 7 的个位规律是:偶数乘以2,奇数乘以2再加5,都只取个位。
乘以 7 的进位规律是:
满 142857... 进1,
满 285714... 进2,
满 428571... 进3,
满 571428... 进4,
满 714285... 进5,
满 857142... 进6

请分析程序流程,填写划线部分缺少的代码。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;

//计算个位 
int ge_wei(int a)
{
    if(a % 2 == 0)
        return (a * 2) % 10;
    else
        return (a * 2 + 5) % 10;
}


//计算进位 
int jin_wei(char* p)
{
    char* level[] = {
        "142857",
        "285714",
        "428571",
        "571428",
        "714285",
        "857142"
    };

    char buf[7];
    buf[6] = '\0';
    strncpy(buf, p, 6);
    
    int i;
    //满足某个数,因为进相应的 i+1位,不满则 i 
    for(i=5; i>=0; i--){
        int r = strcmp(level[i], buf);
        if(r<0) return i+1;
        while(r==0){
            p += 6;
            strncpy(buf, p, 6);
            r = strcmp(level[i], buf);
            //level[i] < buf : i+1
            if(r<0) return i+1;
            //level[i] > buf : 就少进一个位 
            if(r>0) return i;  //填空
        }
    }
    
    return 0;
}


//多位数乘以7
void f(char* s) 
{
    int head = jin_wei(s);
    if(head > 0) printf("%d", head);
    
    char* p = s;
    while(*p){
        int a = (*p-'0');
        int x = (ge_wei(a) + jin_wei(p+1)) % 10;
        printf("%d",x);
        p++;
    }

    printf("\n");
}


int main()
{
//    cout << ge_wei(124) << endl;
    
    f("428571428571");
    f("34553834937543");
    return 0;
}

答案:if (r > 0) return i;  找规律瞎猜的→_→,然后就对了,根据下行文猜猜呢........

第五题:打印图形

 小明在X星球的城堡中发现了如下图形和文字:
rank=3
   * 
  * * 
 *   *  
* * * *


rank=5
               *                                                      
              * *                                                     
             *   *                                                    
            * * * *                                                   
           *       *                                                  
          * *     * *                                                 
         *   *   *   *                                                
        * * * * * * * *                                               
       *               *                                              
      * *             * *                                             
     *   *           *   *                                            
    * * * *         * * * *                                           
   *       *       *       *  
  * *     * *     * *     * *  
 *   *   *   *   *   *   *   * 
* * * * * * * * * * * * * * * *  


ran=6
                               *                                      
                              * *                                     
                             *   *                                    
                            * * * *                                   
                           *       *                                  
                          * *     * *                                 
                         *   *   *   *                                
                        * * * * * * * *                               
                       *               *                              
                      * *             * *                             
                     *   *           *   *                            
                    * * * *         * * * *                           
                   *       *       *       *                          
                  * *     * *     * *     * *                         
                 *   *   *   *   *   *   *   *                        
                * * * * * * * * * * * * * * * *                       
               *                               *                      
              * *                             * *                     
             *   *                           *   *                    
            * * * *                         * * * *                   
           *       *                       *       *                  
          * *     * *                     * *     * *                 
         *   *   *   *                   *   *   *   *                
        * * * * * * * *                 * * * * * * * *               
       *               *               *               *              
      * *             * *             * *             * *             
     *   *           *   *           *   *           *   *            
    * * * *         * * * *         * * * *         * * * *           
   *       *       *       *       *       *       *       *          
  * *     * *     * *     * *     * *     * *     * *     * *         
 *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *        
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *       
                                                                      


小明开动脑筋,编写了如下的程序,实现该图形的打印。


#define N 70


void f(char a[][N], int rank, int row, int col)
{
if(rank==1){
a[row][col] = '*';
return;
}

int w = 1;
int i;
for(i=0; i<rank-1; i++) w *= 2;

____________________________________________;
f(a, rank-1, row+w/2, col);
f(a, rank-1, row+w/2, col+w);
}


int main()
{
char a[N][N];
int i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++) a[i][j] = ' ';

f(a,6,0,0);

for(i=0; i<N; i++){
for(j=0; j<N; j++) printf("%c",a[i][j]);
printf("\n");
}

return 0;
}
请仔细分析程序逻辑,填写缺失代码部分。

答案:f(a, rank-1, row, col+w/2);  扎心,又是找规律写的.......感觉是他递归了行方向,和行列方向,但是没有单独递归列方向.....然后就猜是不是这个......果然是正确的..

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define N 70

// a 6 0 0 
void f(char a[][N], int rank, int row, int col)
{
    if(rank==1){
        a[row][col] = '*';
        return;
    }
    int w = 1;
    int i;
    for(i=0; i< rank-1; i++) 
        w *= 2;
    
    f(a, rank-1, row, col+w/2); 
    
    f(a, rank-1, row+w/2, col);
    f(a, rank-1, row+w/2, col+w);
}


int main()
{
    char a[N][N];
    int i,j;
    for(i=0;i<N;i++)
        for(j=0;j<N;j++) 
            a[i][j] = ' ';
    
    f(a,6,0,0);
    
    for(i=0; i<N; i++){
        for(j=0; j<N; j++) 
            printf("%c",a[i][j]);
        printf("\n");
    }
    
    return 0;
}

第六题:奇怪的分式
6. 上小学的时候,小明经常自己发明新算法。一次,老师出的题目是:

1/4 乘以 8/5
小明居然把分子拼接在一起,分母拼接在一起,答案是:
18/45 (参见图1.png) 老师刚想批评他,转念一想,这个答案凑巧也对啊,真是见鬼! 对于分子、分母都是 1~9 中的一位数的情况,还有哪些算式可以这样计算呢? 请写出所有不同算式的个数(包括题中举例的)。 显然,交换分子分母后,例如:4/1 乘以 5/8 是满足要求的,这算做不同的算式。 但对于分子分母相同的情况,2/2 乘以 3/3 这样的类型太多了,不在计数之列! 注意:答案是个整数(考虑对称性,肯定是偶数)。请通过浏览器提交。不要书写多余的内容。

答案:14;注意:分子分母相同的,不在计数之内,即分子/分母 != 1

#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;

void solve()
{
    int ans = 0;
    for (int a = 1; a <= 9; a++)
    {
        for (int b = 1; b <= 9; b++)
        {
            for (int c = 1; c <= 9; c++)
            {
                for (int d = 1; d <= 9; d++)
                {
                    double fenzi = a*10 + b;
                    double fenmu = c*10 + d;
                    double chenzi = a*b;
                    double chenmu = c*d;
                    if (fenzi/fenmu != 1 && fenzi/fenmu == chenzi/chenmu) {
                        ans++;
//                        cout << fenzi << "/" << fenmu << "=" << fenzi/fenmu << endl;
//                        cout << "Debug: " << chenzi << "/" << chenmu << "=" << chenzi/chenmu << endl; 
                    }
                }
            }
        }
    }
    cout << ans << endl;
}

int main()
{
    solve();
    
    return 0;
}

第七题:六角填数

    如图【1.png】所示六角形中,填入1~12的数字。

    使得每条直线上的数字之和都相同。

    图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少?

请通过浏览器提交答案,不要填写多余的内容。

答案:10

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

void solve()
{
    int l_1_1 = 1;
    int l_2_1 = 8;
    int l_2_2 = 0, l_2_3 = 0, l_2_4 = 0,
        l_3_1 = 0, l_3_2 = 0,
        l_4_1 = 0, l_4_2 = 0, l_4_3 = 0, l_4_4 = 0,
        l_5_1 = 3;
    int a[] = {2,4,5,6,7,9,10,11,12};
    do {
//        for (auto e : a) {
//            cout << e << " ";
//        }
//        cout << endl;
        l_2_2 = a[0],
        l_2_3 = a[1],
        l_2_4 = a[2],
        l_3_1 = a[3],
        l_3_2 = a[4],
        l_4_1 = a[5],
        l_4_2 = a[6],
        l_4_3 = a[7],
        l_4_4 = a[8]; 
        
        int line1 = l_1_1 + l_2_2 + l_3_1 + l_4_1;
        int line2 = l_1_1 + l_2_3 + l_3_2 + l_4_4;
        int line3 = l_2_1 + l_2_2 + l_2_3 + l_2_4;
        int line4 = l_2_1 + l_3_1 + l_4_2 + l_5_1;
        int line5 = l_4_1 + l_4_2 + l_4_3 + l_4_4;
        int line6 = l_5_1 + l_4_3 + l_3_2 + l_2_4;
        if (line1==line2 && line2==line3 && line3==line4 && line4==line5 && line5==line6 )
        {
            cout << line1 << ":" << line2 << ":" << line3 << ":" << line4 << ":" << line5 << ":" << line6 << endl;
            cout << l_3_1 << endl;
        }
    } while(next_permutation(a, a+9));
    
}

int main()
{
    solve();
    
    return 0;    
} 

有点气.....数组不小心多写了一个 1,怎么也算不出来答案。。检查了半天。。。

第八题:蚂蚁感冒

  长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。 

    每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。

    当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。

    这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。

    请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。

【数据格式】

    第一行输入一个整数n (1 < n < 50), 表示蚂蚁的总数。

    接着的一行是n个用空格分开的整数 Xi (-100 < Xi < 100), Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。其中,第一个数据代表的蚂蚁感冒了。

    要求输出1个整数,表示最后感冒蚂蚁的数目。

例如,输入:
3
5 -2 8
程序应输出:
1
再例如,输入:
5
-10 8 -20 12 25
程序应输出:
3
资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms

 第八题:蚂蚁感冒

题解:其实不用想什么掉头问题啥的,就想象他们是交叉而过。。一样会传染其他的蚂蚁啊。(代码设置的标志条件,好像都没有用,笑哭)

这题就是标记感冒蚂蚁位置:

1. 先按距离左端点 距离绝对值 对所有蚂蚁排个序;

2. 然后判断 感冒蚂蚁位置 如果大于0,即他左边跟他同向的蚂蚁都会因为掉头的缘故而感冒(这样想好像不严谨,不一定会掉头啊,这样就可以加个判断条件啊,就是判断他是否会掉头,就是有比他距离大的并且方向相反的蚂蚁,则标志为会掉头);跟这只蚂蚁反向,但是距离左端点位置大的蚂蚁,都会感冒。

3. 如果小于0,则他右边跟他同向的蚂蚁,都会因为掉头的缘故感冒;跟这只蚂蚁反向,但是距离左端点位置比他小的蚂蚁,都会感冒。

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

int n;
const int maxn = 50 + 10;
struct Ant {
    int x;
    int ok;
    Ant(int x = 0, bool ok = false) : x(x), ok(ok) {
    }
}ants[maxn];

bool cmp(Ant a, Ant b)
{
    return abs(a.x) < abs(b.x);
}

void solve()
{
    int ans = 1;
    int ill = 0;
    
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> ants[i].x;
        if (i == 0) {
            ill = ants[i].x;
            ants[i].ok = true;
        } 
    }
    sort(ants, ants + n, cmp);
    
    int flag = 0;
    for (int i = 0; i < n; i++)
    {
        if (ill > 0) {
            if (abs(ants[i].x) > ill && ants[i].x < 0) {
                flag = 1;
                break;
            }
        }
        else {
            if (ants[i].x < abs(ill) && ants[i].x > 0) {
                flag = 1;
                break;
            }
        }
    }
    
    for (int i = 0; i < n; i++)
    {
        if (ill > 0) 
        {
            if (ants[i].x > 0 && ants[i].x < ill && flag) {
                ans++;
            }
            if (ants[i].x < 0 && abs(ants[i].x) > ill) {
                ans++;
            }
        }
        else 
        {
            if (ants[i].x < 0 && ants[i].x < ill && flag) {
                ans++;
            }    
            if (ants[i].x > 0 && ants[i].x < abs(ill)) {
                ans++;
            }
        }
    }
    cout << ans << endl;
    
}

int main()
{
    solve();
    
    return 0;
}

 第九题 地宫取宝

//不太熟悉动态规划的题目...........参考了网上,放弃放弃,反正前面都会,佛系学算法..........

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring> 
#include <queue>
using namespace std;

const int maxn = 100;
const long long INF = 1000000007; //用来取余 
int maze[maxn][maxn];

int d[52][52][14][14]; //行,列,k个数,value
int n, m, k;           //[n,m], k件宝贝
long long ans;         //方案数 

int dfs(int r, int c, int sum, int Max); //当前位置 
void input();
void solve();

void input()
{
    memset(d, -1, sizeof(d));
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++) {
            scanf("%d", &maze[i][j]);
        }
    }
}

int dfs(int r, int c, int sum, int Max)
{
    if (d[r][c][sum][Max + 1] != -1) {      //已经遍历完, 并设置了结果 
        return d[r][c][sum][Max + 1];       //返回结果 
    }

    int t = 0;

    if (r == n - 1 && c == m - 1) {         //到达入口 
                                             
        if (maze[r][c] > Max) {             //可以再拿一个宝物 
            if (sum == k || sum == k - 1)   //如果已经到了 k 或是  k-1,方案++ 
                t++;
        }
        else if (sum == k) {                //不能拿时候,则此时就需要为k, 方案++ 
            t++;
        }
        return d[r][c][sum][Max + 1] = t;   //更新方案数 
    }

    if (r + 1 < n) {
        if (maze[r][c] > Max) {            //可以拿 
            t += dfs(r + 1, c, sum + 1, maze[r][c]);      //选择拿 
            t %= INF;
            t += dfs(r + 1, c, sum, Max);                 //选择不拿 
            t %= INF;
        }
        else {
            t += dfs(r + 1, c, sum, Max);  //不可以拿 
            t %= INF;
        }
    }
    if (c + 1 < m) {
        if (maze[r][c] > Max) {
            t += dfs(r, c + 1, sum + 1, maze[r][c]);
            t %= INF;
            t += dfs(r, c + 1, sum, Max);
            t %= INF;
        }
        else {
            t += dfs(r, c + 1, sum, Max);
            t %= INF;
        }
    }
    d[r][c][sum][Max + 1] = t;         //将方案数 保存在Max + 1 处 
    return d[r][c][sum][Max + 1];      //返回方案数 
}

void solve()
{
    input();
    ans = dfs(0, 0, 0, -1);
    cout << ans << endl;
}

int main()
{
    solve();
    return 0;
}

 

 

 

 

 

 

推荐阅读