美文网首页
蓝桥杯第五届B组预选

蓝桥杯第五届B组预选

作者: _弓长_大人 | 来源:发表于2018-09-25 12:44 被阅读43次

    第一题:啤酒和饮料(4' )

    啤酒每罐2.3元,饮料每罐1.9元。小明买了若干啤酒和饮料,一共花了82.3元。
    我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐啤酒。
    注意:答案是一个整数。请通过浏览器提交答案。
    不要书写任何多余的内容(例如:写了饮料的数量,添加说明文字等)。
    

    1)穷举
    2)利用工具计算

    答案:11
    考虑精度的话 *10 就可以了,得到两个答案,因为已知啤酒比饮料的数量少,所以只有一个答案

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int ans=0;
    int a[5];
    int visited[5];
    int num[12]={1,2,3,4,6,7,8,9,11,12,13,14};
    int d[4]={-1,1,5,-5}; 
    int i,j,k,l,m; 
    void dfs(int n)//判断这五个数是不是一个连通块 
    {
        for(int i=0;i<4;i++)// 
        {
            int t=a[n]+d[i];
            if(t>14||t<1||t==5||t==10)
            continue;
            for(int j=0;j<5;j++)
            {
                if(visited[j]!=1&&a[j]==t)
                {
                    visited[j]=1;
                    dfs(j);
                }
            }
        }
    }
    int  main()
    {
        double a=2.3;
        double b=1.9;
        int i,j;
        int f=0;
        for(i=0;i<40;i++)
        {
            for(j=0;j<50;j++)
            {
                if(2.3*i+1.9*j==82.3)
                cout<<i<<" "<<j<<" "<<2.3*i+1.9*j<<endl;
            }
        }
    return 0;
    }
    

    第二题:切面条(5' )

     一根高筋拉面,中间切一刀,可以得到2根面条。
    如果先对折1次,中间切一刀,可以得到3根面条。
    如果连续对折2次,中间切一刀,可以得到5根面条。
    那么,连续对折10次,中间切一刀,会得到多少面条呢?
    答案是个整数,请通过浏览器提交答案。不要填写任何多余的内容。
    

    1 找规律
    2 递推

    答案:1025
    规律 是 2^n+1

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int  main()
    {
        cout<<((1<<10)+1)<<endl; 
    return 0;
    }
    

    第三题:李白打酒 (8' )

    话说大诗人李白,一生好饮。幸好他从不开车。
    一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
    
    无事街上走,提壶去打酒。
    逢店加一倍,遇花喝一斗。
    
    这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。 
    
    请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
    
    注意:通过浏览器提交答案。答案是个整数。不要书写任何多余的内容。
    

    1、把数字转化为二进制,因为只用花跟店两种情况,对应0,1 两个数字

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int num[15];
    int  main()
    {
        int ans=0;
        int sum=2;
        for(int i=0;i<(1<<14)-1;i++)
        {
            int t=i;
            sum=2;
        int hua=0;
        int jiu=0;
            for(int j=0;j<14;j++)//15位2进制 
            {
                int temp=t&1;//位数为1则为 1 
                num[j]=temp;
                //cout<<temp;
                if(temp)//1为花,0为酒店
                {
                    hua++;
                    sum--;
                } 
                if(temp==0)
                {
                    jiu++;
                    sum=sum*2;
                }
                if(sum<=0)
                break;
                t=t>>1;
            }
            //cout<<endl;
            if(sum==1&&hua==9&&jiu==5)
            {
                for(int i=0;i<14;i++)
                {
                    cout<<num[i];
                 } 
                 cout<<endl; 
                ans++;
            } 
        }
        cout<<ans<<endl;
    return 0;
    }
    

    2 递归,搜素

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int ans=0;
    void dfs(int hua,int dian,int pre,int sum)
    {
        if(hua==0&&dian==0)
        {
            if(pre==0&&sum==0)
            {
                ans++;
            }
        }
        if(hua>0)
        {
            pre=0;
            dfs(hua-1,dian,pre,sum-1);
        }
            if(dian>0)//店是 1 
        {
            pre=1;
            dfs(hua,dian-1,pre,sum*2);
        }
    } 
    int  main()
    {
        dfs(10,5,0,2);
        cout<<ans<<endl;
    return 0;
    }
    
    

    第四题:史丰收速算(7' )

    史丰收速算法的革命性贡献是:从高位算起,预测进位。不需要九九表,彻底颠覆了传统手算!
    速算的核心基础是: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
    请分析程序流程,填写划线部分缺少的代码。
    

    //计算个位
    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;
    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);
    if(r<0) return i+1;
    ______________________________; //填空
    }
    }

    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()
    {
    f("428571428571");
    f("34553834937543");
    return 0;
    }

    注意:通过浏览器提交答案。只填写缺少的内容,不要填写任何多余的内容(例如:说明性文字)

    答案: if(r>0)return i

    1 读懂题意,基本看懂程序,试探运行看结果。

    第五题:打印图形 (12' )

    小明在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)

    第六题:奇怪的分式(11')

    上小学的时候,小明经常自己发明新算法。一次,老师出的题目是:
    1/4 乘以 8/5 
    小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图1.png)
    
    老师刚想批评他,转念一想,这个答案凑巧也对啊,真是见鬼!
    对于分子、分母都是 1~9 中的一位数的情况,还有哪些算式可以这样计算呢?
    
    请写出所有不同算式的个数(包括题中举例的)。
    显然,交换分子分母后,例如:4/1 乘以 5/8 是满足要求的,这算做不同的算式。
    但对于分子分母相同的情况,2/2 乘以 3/3 这样的类型太多了,不在计数之列!
    

    注意:答案是个整数(考虑对称性,肯定是偶数)。请通过浏览器提交。不要书写多余的内容。

    答案:14
    1 穷举

    #include<iostream>
    using namespace std;
    int main()
    {
        int ans=0;
        int a,b,c,d;
        for(a=1;a<10;a++)
        {
            for(b=1;b<10;b++)
            {
                for(c=1;c<10;c++)
                {
                    for(d=1;d<10;d++)
                    {
                        if(a==b&&d==c)
                        {
                            continue;
                        }
                        else
                        {
                            int x=(10*a+d)*b*c;
                            int y=(a*d)*(10*b+c);
                        
                            if(x==y)
                            {
                                ans++;
                            }
                        }
                        
                    }
                }
            }
        }
        cout<<ans;
        return 0; 
    } 
    

    第7题:六角填数(12')

    如图所示六角形中,填入1~12的数字。
    使得每条直线上的数字之和都相同。
    图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少?
    

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

    1 深度优先搜素 dfs 从上到下,从左到右从1到12标记每一个点。初始化1,8,3. 要求的地方点的标记为6. 碰到1,2,12,就直接dfs下一个。
    答案 :10
    有一篇蓝桥杯暴力搜索说过这个

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int a[12]={1,2,3,4,5,6,7,8,9,10,11,12};
    bool fun()
    {
        if(a[0]+a[2]+a[5]+a[6]==26)
        {
                if(a[6]+a[7]+a[8]+a[10]==26)
        {
                if(a[0]+a[3]+a[9]+a[10]==26)
        {
                if(a[1]+a[2]+a[3]+a[4]==26)
        {
                if(a[1]+a[5]+a[7]+a[11]==26)
        {
                if(a[4]+a[9]+a[8]+a[11]==26)
        {
            return true;
        }
        }
        }
        }
        }
        }
        return false;
    }
    int  main()
    {
    //    a[12]={1,2,3,4,5,6,7,8,9,10,11,12};
        do{
            if(a[0]==1&&a[1]==8&&a[11]==3)
            {
                if(fun())
                {
                    cout<<a[5]<<endl;
                    break;
                }
            }
        }while(next_permutation(a,a+12));
    return 0;
    }
    

    第八题:蚂蚁感冒(10')

    长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

    请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

    所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

    注意: main函数需要返回0
    注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
    注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

    提交时,注意选择所期望的编译器类型。

    1 模拟
    2 分析规律
    两个蚂蚁碰头。然后都反向。与两个蚂蚁都不反向,直接穿透爬行没有区别。
    具体思路:第一个输入时感冒的蚂蚁,它有两种方向,向左或向右。
    如果它是向左的:
    那么对一组输入数据,输入完之后我们可以知道,在0-100这根直杆上,分别分布着一些蚂蚁,每只蚂蚁都有一个朝向。
    那么那只感冒的蚂蚁所在直杆的位置就将直杆以它为中心分成左右两部分,
    因为感冒的那只是向左的,所以它左边的直杆上的蚂蚁,只要是向右的,那么到最后都会被感冒。此时,只要它的左边的直杆上有一只向右走的蚂蚁,那么它右边的直杆上向左走的蚂蚁,走到最后肯定也会被感冒。如果它左边没有一只向右走的蚂蚁,那么最后只会有它这一只感冒。

    如果它是向右走的计算方法同理。

    所以走到最后会被感冒的总数就是,对第一个感冒的蚂蚁,在直杆上,它要走的方向的那一边的所有蚂蚁中,向它相反的方向走的蚂蚁的总数,如果总数不为0,就再加上它在直杆的位置的右边的直杆上的蚂蚁中和它的行动方向相同的蚂蚁的总数。最后再加上它自己本身就是answer了。

    特殊情况:1第一个感冒的蚂蚁一直没有反向,结果为1.因为没有跟感冒蚂蚁碰头的。
    2.第一个感冒蚂蚁在最左边且向左爬,或在最右边且向右爬。结果为1.

    #include<iostream>
    #include<cmath>
    using namespace std;
    int  route[200];
    int main()
    {
        int n;
        cin>>n;
        int b,a;
        int x;
        for(int i=0;i<n;i++)
        {
            cin>>a;
            if(i==0)
            x=a;//这一只感冒的蚂蚁 
            b=abs(a);
        route[b]=b/a;
        }
        b=abs(x);
        int ans=1;
        int f=0;
        if(x>0)//向右 
        {
            for(int j=x+1;j<=100;j++)
            {
                if(route[j]<0)
                {
                    f=1;
                    ans++;
                }
             } 
             if(f==1)
             {
                 for(int j=1;j<x;j++)
             {
                if(route[j]>0)
                {
                    ans++;
                 }
             }  
             }
        }
        else//感冒蚂蚁向左时 
        {
            f=0; 
                for(int j=1;j<(-x);j++)
            {
                if(route[j]>0)
                {
                    f=1;
                    ans++;
                }
             } 
             if(f==1)
             {
                 for(int j=(-x+1);j<=100;j++)
             {
                if(route[j]<0)
                {
                    ans++;
                 }
             }  
             }
        }
        cout<<ans;
        return 0; 
    } 
    

    第九题:地宫取宝(12')

    X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
    地宫的入口在左上角,出口在右下角。
    小明被带到地宫的入口,国王要求他只能向右或向下行走。
    走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
    当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
    
    请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。
    

    【数据格式】

    输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)
    接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值
    要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。
    

    例如,输入:
    2 2 2
    1 2
    2 1
    程序应该输出:
    2

    再例如,输入:
    2 3 2
    1 2 3
    2 1 5
    程序应该输出:
    14

    资源约定:
    峰值内存消耗 < 256M
    CPU消耗 < 1000ms

    请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

    所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

    注意: main函数需要返回0
    注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
    注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

    提交时,注意选择所期望的编译器类型

    法一:暴力搜索,虽然肯定会超时,但是,我在蓝桥杯官网提交了一下,有42 分→ ,还是可以了

    #include<iostream>
    using namespace std;
    int mapp[51][52];
    int n,m,k;
    int ans=0;
    int d[2][2]={1,0,0,1};//向下和向右 
    void dfs(int ma,int x,int y,int co)
    {
        if(x==(n-1)&&y==(m-1))
        {
            if(co==k)
            {
                ans++;//已经到了K件物品,而且没有拿最后一件 
            }
            if(co==(k-1)&&mapp[x][y]>ma)
            {
                ans++;
            }
            ans=ans%1000000007; 
        }
        for(int i=0;i<2;i++)
        {
            int xx=x+d[i][0];
            int yy=y+d[i][1];
            if(xx>=0&&xx<n&&yy>=0&&yy<m)
            {
                dfs(ma,xx,yy,co);//到达X,Y时候没有拿 
                if(mapp[x][y]>ma)
                {
                    dfs(mapp[x][y],xx,yy,co+1);//达到x,y时候拿了 
                }
            }
        } 
    }
    int main()
    {
        cin>>n>>m>>k;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                cin>>mapp[i][j];
            }
        } 
        dfs(-1,0,0,0);
        cout<<ans;
        return 0;
    } 
    

    那到底应该肿么做,才能得全分呐,就要降低它的时间复杂度。
    法二:记忆化搜索

    
    

    第十题:小朋友排队(19')

    n 个小朋友站成一排。现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。
    每个小朋友都有一个不高兴的程度。开始的时候,所有小朋友的不高兴程度都是0。
    如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。当要求某个小朋友第k次交换时,他的不高兴程度增加k。
    
    请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。
    如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。
    

    【数据格式】
    输入的第一行包含一个整数n,表示小朋友的个数。
    第二行包含 n 个整数 H1 H2 … Hn,分别表示每个小朋友的身高。
    输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。

    例如,输入:
    3
    3 2 1
    程序应该输出:
    9

    【样例说明】
    首先交换身高为3和2的小朋友,再交换身高为3和1的小朋友,再交换身高为2和1的小朋友,每个小朋友的不高兴程度都是3,总和为9。

    【数据规模与约定】
    对于10%的数据, 1<=n<=10;
    对于30%的数据, 1<=n<=1000;
    对于50%的数据, 1<=n<=10000;
    对于100%的数据,1<=n<=100000,0<=Hi<=1000000。

    资源约定:
    峰值内存消耗 < 256M
    CPU消耗 < 1000ms

    请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

    所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

    注意: main函数需要返回0
    注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
    注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

    提交时,注意选择所期望的编译器类型。

    逆序对的问题,如果解决的知道如何在nlogn 的 时间范围内求的逆序对,这个问题就迎刃而解,参考
    利用 数状数组求解逆序对

    
    #include<iostream>
    #include<cstring>
    using namespace std;
    int c1[1000001],c2[1000001],b[1000001];
    typedef long long ll;
    ll sum[100001];
    int num[100001];
    int n;
    void init()
    {
        sum[0]=0;
        for(int i=1;i<n;i++)
        {
            sum[i]=sum[i-1]+i;
        }
    }
    int lowbit(int x)
    {
        return x&(-x);
     } 
    void add(int pos,int *c)
    {
        while(pos<=1000010)
        {
            c[pos]++;
            pos+=lowbit(pos);
        }
    }
    int sumof(int pos,int *c)
    {
        int s=0;
        while(pos>0)
        {
            s+=c[pos];
            pos-=lowbit(pos);
        }
        return s;
    }
    int main()
    {
        memset(c1,0,sizeof(c1));
        memset(c2,0,sizeof(c2));
        memset(b,0,sizeof(b));
        cin>>n;
        init();
        for(int i=0;i<n;i++)
        {
            cin>>num[i];
            add(num[i]+1,c1);
            b[i]+=i+1-sumof(num[i]+1,c1);
         } 
         ll ans=0;
         for(int i=n-1;i>=0;i--)
         {
            add(num[i]+1,c2);
            b[i]+=sumof(num[i],c2);
            ans+=sum[b[i]];
         }
         cout<<ans<<endl;
        return 0;
     }
    

    相关文章

      网友评论

          本文标题:蓝桥杯第五届B组预选

          本文链接:https://www.haomeiwen.com/subject/lsmmnttx.html