第八届蓝桥杯大赛个人赛决赛(软件类)真题C++

时间:2021-12-05 20:03:57

哥德巴赫分解

哥德巴赫猜想认为:不小于4的偶数都可以表示为两个素数的和。

你不需要去证明这个定理,但可以通过计算机对有限数量的偶数进行分解,验证是否可行。

实际上,一般一个偶数会有多种不同的分解方案,我们关心包含较小素数的那个方案。
对于给定数值范围,我们想知道这些包含较小素数方案中最大的素数是多少。

比如,100以内,这个数是19,它由98的分解贡献。

你需要求的是10000以内,这个数是多少?

注意,需要提交的是一个整数,不要填写任何多余的内容(比如,说明性的文字)

答案:173

 1 #include <bits/stdc++.h>
 2 
 3 /**
 4 @author:d g w
 5 */
 6 using namespace std;
 7 typedef long long LL ;
 8 
 9 const int maxn=1e4;
10 
11 int prime[maxn];
12 int pnum;
13 int hashtable[maxn]={false};
14 void f(){
15     for(int i=2;i<maxn;i++){
16         if(hashtable[i]==false){
17             prime[pnum++]=i;
18             for(int j=i+i;j<maxn;j+=i){
19                 hashtable[j]=true;
20             }
21         }
22     }
23 }
24 
25 int main()
26 {
27     f();
28     for(int i=0;i<pnum;i++){
29         cout<<prime[i]<<" ";
30    }cout<<endl;
31    int ans[maxn]={0},re=0;bool flag=true;
32     for(int i=6;i<=10000;i+=2){
33         for(int j=2;j<=i/2;j++){
34             if(hashtable[j]==false&&hashtable[i-j]==false){
35                 cout<<i<<"="<<j<<"+"<<i-j<<endl;
36                 ans[re++]=min(j,i-j);
37                 break;
38             }
39         }
40     }
41     int res=0;
42     for(int j=0;j<re;j++){
43         res=max(res,ans[j]);
44     }
45     cout<<res;
46     system("pause");
47     return 0;
48 }

 

 - 比较容易出错的枚举算法,很多细节需要注意;

 

#include <bits/stdc++.h>

/**
@author:d g w
*/
using namespace std;
typedef long long LL ;

const int maxn=1e5;

int prime[maxn];
int pnum;
int hashtable[maxn]= {false};
void f()
{
    for(int i=2; i<maxn; i++)
    {
        if(hashtable[i]==false)
        {
            prime[pnum++]=i;
            for(int j=i+i; j<maxn; j+=i)
            {
                hashtable[j]=true;
            }
        }
    }
}

int main()
{
    f();
    for(int i=0; i<pnum; i++)
    {
        cout<<prime[i]<<" ";
    }
    cout<<endl;
    int ans[100000]= {0},re=0;

    for(int i=6; i<=10000; i+=2)
    {
        bool flag=true;
        for(int j=0; prime[j]<200; j++)//200以内就够了,可以打印出来看看规律
        {
            for(int k=j+1; prime[k]<10000; k++)//易错点 顶峰值必须相近 要保证有最小值另一个加数必须大
            {
                if((prime[j]+prime[k])==i)
                {
                    cout<<prime[j]<<"+"<<prime[k]<<endl;
                    ans[re++]=min(prime[j],prime[k]);
                    flag=false;
                }
            }
            if(flag==false)break;
        }
    }

    int res=0;
    for(int j=0; j<re; j++)
    {
        res=max(res,ans[j]);
    }
    cout<<res;
    system("pause");
    return 0;
}

 

标题:数字划分


w星球的长老交给小明一个任务:
1,2,3...16 这16个数字分为两组。
要求:
这两组数字的和相同,
并且,两组数字的平方和也相同,
并且,两组数字的立方和也相同。

请你利用计算机的强大搜索能力解决这个问题。
并提交1所在的那个分组的所有数字。

这些数字要从小到大排列,两个数字间用一个空格分开。
即类似:1 4 5 8 ... 这样的答案。

注意,只提交这一组数字,不要填写任何多余的内容。

----------------------------------------
笨笨有话说:
只要一个组的成员确定了,另一个组的成员也就确定了。枚举一个组的成员就可以了。
凭直觉,两个组的成员数目不会差太多吧。
歪歪有话说:
既然求 1 所在的那个组,那只要枚举剩余的成员就可以了。
貌似都是8个成员的可能性很大啊。

answer:1 4 5 8 9 10 15 16

 1 #include <bits/stdc++.h>
 2 /**
 3 @author:d g w
 4 */
 5 using namespace std;
 6 typedef long long LL ;
 7 
 8 const int maxn=1e5;
 9 
10 int prime[maxn];
11 int pnum;
12 int hashtable[maxn]= {false};
13 void f()
14 {
15     for(int i=2; i<maxn; i++)
16     {
17         if(hashtable[i]==false)
18         {
19             prime[pnum++]=i;
20             for(int j=i+i; j<maxn; j+=i)
21             {
22                 hashtable[j]=true;
23             }
24         }
25     }
26 }
27 int a[16]={1,4,5,8,2,3,6,7,9,10,11,12,13,14,15,16};
28 int main()
29 {   int flag=true;
30     do{
31         if(!flag)break;
32         //1 4 5 8
33         if(a[0]==1&&a[1]==4&&a[2]==5&&a[3]==8){
34             int x=a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7];
35             int y=a[8]+a[9]+a[10]+a[11]+a[12]+a[13]+a[14]+a[15];
36             if(x==y){
37                 if((x*x)==(y*y)){
38                     if((x*x*x)==(y*y*y)){
39                         //a[0]+a[1]+[2]+a[3]+a[4]+a[5]+a[6]+a[7]
40                         if(a[0]<a[1]&&a[1]<a[2]&&a[2]<a[3]&&a[3]<a[4]&&a[4]<a[5]&&a[5]<a[6]&&a[6]<a[7]){
41                         cout<<a[0]<<' '<<a[1]<<' '<<a[2]<<' '<<a[3]<<' '<<a[4]<<' '<<a[5]<<' '<<a[6]<<' '<<a[7]<<endl;
42                         flag=false;
43                         }
44                     }
45                 }
46             }
47         }
48 
49     }while(next_permutation(a+4,a+16));
50     system("pause");
51     return 0;
52 }

 

标题:表达式计算

虽然我们学了许久的程序设计,但对于简单的四则混合运算式,如果让我们完全白手起家地编程来解析,还是有点棘手。

这里,我们简化一下问题,假设只有加法和乘法,并且没有括号来改变优先级。
再假设参加运算的都是正整数。

在这么多的限制条件下,表达式的解析似乎简单了许多。
下面的代码解决了这个问题。请仔细阅读源码,并填写划线部分缺少的代码。

#include <stdio.h>

int f3(const char* s, int begin, int end)
{
int sum = 0;
int i;
for(i=begin; i<end; i++){
if(s[i]==' ') continue;
sum = sum * 10 + (s[i]-'0');
}
return sum;
}

int f2(const char* s, int begin, int end)
{
int p = begin;
int pro = 1;
while(1){
int p0 = p;
while(p!=end && s[p]!='*') p++;
pro *= _______________________________; //填空
if(p==end) break; 
p++;
}
printf("f2: pro=%d\n", pro);
return pro;
}

int f(const char* s)
{
int p = 0;
int sum = 0;
while(1){
int p0 = p;
while(s[p]!=0 && s[p]!='+') p++;
sum += f2(s,p0,p);
if(s[p]==0) break;
p++;
}

return sum;
}

int main()
{
int x = f("12+18+5*4*3+10");
printf("%d\n", x);
return 0;
}

 


answer:f3(s,p0,p)

注意:只填写划线处缺少的内容,不要填写已有的代码或符号,也不要填写任何解释说明文字等。

 


标题: 小数第n位

我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数。
如果我们把有限小数的末尾加上无限多个0,它们就有了统一的形式。

本题的任务是:在上面的约定下,求整数除法小数点后的第n位开始的3位数。

输入:
一行三个整数:a b n,用空格分开。a是被除数,b是除数,n是所求的小数后位置(0<a,b,n<1000000000)
输出:
一行3位数字,表示:a除以b,小数后第n位开始的3位数字。

比如:
输入:
1 8 1 0.125

程序应该输出:
125

再比如:
输入:
1 8 3

程序应该输出:
500

再比如:
输入:
282866 999000 6
282866 999 6
程序应该输出:
914

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

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

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

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

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

----------------------------------------
笨笨有话说:
这个除法小学就会算啊,模拟手算除法的过程就可以了吧。
只是数有点大啊....
管它呢,能算多远算多远....

歪歪有话说:
如果我能确定循环节从哪里开始到哪里结束,再大的数不过就是与它取模的余数等价啊

 

#include <bits/stdc++.h>
/**
@author:d g w
*/
using namespace std;
typedef long long LL ;

const int maxn=1e3;

LL MOD=1e9+7;
LL P=1e7+19;



int main()
{
    stringstream ss;
    string str,str2;

    LL a,b,n;
    cin>>a>>b>>n;
    cout<<setprecision(12)<<(double)a/b<<endl;
    ss<<setprecision(12)<<(double)a/b;
    ss>>str;
    int j=0;
    cout<<str<<endl;
    for(int i=n+1;i<str.length();i++){
           str2[j++]=str[i];
    }
    if(j==1){
        cout<<str2[0]<<"00";
    }else{
        for(int i=0;i<j&&i<3;i++){
            cout<<str2[i];
        }
    }
    system("pause");
    return 0;
}

 扑克牌 

给定4张扑克牌 点数为:1~10
用+ - * / 运算,3个运算符结果正好为24

 

#include <bits/stdc++.h>
/**
@author:d g w
*/
using namespace std;
typedef long long LL ;

const int maxn=1e3;

LL MOD=1e9+7;
LL P=1e7+19;

const int N=1e5;

char rand_op(){
    int x=rand()%4;
    if(x==0)return '+';
    if(x==1)return '-';
    if(x==3)return '*';
    return '/';
}

char op(int a,int b,char opr){
    if(opr=='+')return (a+b)+'0';
    if(opr=='*')return (a*b)+'0';
    if(opr=='-')return (a-b)+'0';
    if(a%b!=0) return 'n';
    return a/b;
}

bool ji_suan(char buf[]){
      stack<char> stk;
      for(int i=0;i<7;i++){
          if(buf[i]=='+'||buf[i]=='-'||buf[i]=='*'||buf[i]=='/'){
                int a=stk.top()-'0';stk.pop();
                int b=stk.top()-'0';stk.pop();
                if(op(a,b,buf[i])=='n'){
                    return false;
                }else{
                    stk.push(op(a,b,buf[i]));
                }
          }else{
            stk.push(buf[i]);
          }
      }
    if(stk.size()==1 && (stk.top()-'0')==24)
            return true;
    return false;
}
void show(char buf[]){
    stack<char> stk;
      for(int i=0;i<7;i++){
          if(buf[i]=='+'||buf[i]=='-'||buf[i]=='*'||buf[i]=='/'){
                int a=stk.top()-'0';stk.pop();
                int b=stk.top()-'0';stk.pop();
                if(op(a,b,buf[i])=='n'){
                    //return false;
                }else{
                    stk.push('('+stk.top()+buf[i]+stk.top()+')');
                }


          }else{
            stk.push(buf[i]);
          }
      }
    cout<<stk.top();
}


void f(char str[]){
    for(int z=0;z<1e4;z++){
        char buf[7];
        for(int i=0;i<4;i++)buf[i]==str[i];
        for(int i=4;i<7;i++)buf[i]==rand_op();

        random_shuffle(buf,buf+7);
        if(ji_suan(buf)){
            show(buf);
        }
    }

}


int main()
{
    srand((unsigned)time(NULL));
    char s[4];
    while(1){
        cout<<"input number 4"<<endl;
        for(int i=0;i<4;i++){
            cin>>s[i];
        }
        f(s);
    }
    system("pause");
    return 0;
}