2019蓝桥杯省赛B组
A.组队
方法一:人脑计算(每次选最大,但是一个人不能当两个位)
最大值:98+99+98+97+98
法二:枚举
#include<iostream> using namespace std; //每个位置各编号的评分情况 int one[20] = {97, 92, 0, 0, 89, 82, 0, 0, 0, 95, 0, 0, 94, 0, 0, 0, 98, 93, 0, 0}; int two[20] = {90, 85, 0, 0, 83, 86, 0, 97, 0, 99, 0, 0, 91, 83, 0, 0, 83, 87, 0, 99}; int three[20] = {0, 96, 0, 0, 97, 0, 0, 96, 89, 0, 96, 0, 0, 87, 98, 0, 99, 92, 0, 96}; int four[20] = {0, 0, 0, 80, 0, 0, 87, 0, 0, 0, 97, 93, 0, 0, 97, 93, 98, 96, 89, 95}; int five[20] = {0, 0, 93, 86, 0, 0, 90, 0, 0, 0, 0, 98, 0, 0, 98, 86, 81, 98, 92, 81}; int main() { int m=0; //考点:多重for循环遍历且不能选重复! for(int i=0;i<20;i++){ for(int j=0;j<20;j++){ if(i==j)continue; for(int k=0;k<20;k++){ if(i==k||j==k)continue; for(int p=0;p<20;p++){ if(p==i||p==j||p==k)continue; for(int q=0;q<20;q++){ if(q==i||q==j||q==k||q==p)continue; m=max(m,one[i]+two[j]+three[k]+four[p]+five[q]); } } } } } cout<<m; return 0; } 答案:490B.年号子串
#include <iostream> using namespace std; int main() { cout<<"BYQ"; // 请在此输入您的代码 return 0; } 分析: 类似于26进制, 权重:个位为26的0次方,十位为26的1次方 然后对于A~Z单个来说为1~26再乘以这一位权重。 答案:BYQC.数列求值
//考点:类似斐波拉契数列+取模运算
#include<bits/stdc++.h> using namespace std; typedef long long int ll; const ll N=20191000; ll a[N]; int main(){ a[1]=1; a[2]=1; a[3]=1; for(int i=4;i<=20190324;i++) { a[i]=(a[i-1]+a[i-2]+a[i-3])%10000;//对于只求最后n位数就每次%10的n次方,不能直接求整个数因为数太大所以才让求后几位! } cout<<a[20190324]; return 0; } 答案:4659D.数的分解
#include<bits/stdc++.h>using namespace std;
typedef long long int ll;
ll ans;
bool check(int a){
while(a){
if(a%10==2||a%10==4)return true;
a/=10;
}
return false;
}
int main(){
for(int i=1;i<=2019;i++){
if(check(i)) continue;
for(int j=i+1;j<=2019;j++){
if(check(j))continue;
for(int p=j+1;p<=2019;p++){
if(check(p))continue;
if(i+j+p==2019)ans++;
}
}
}
cout<<ans;
return 0;
} 答案:40785
E.迷宫(有问题)
/* 步数最少用bfs bfs依靠队列 每次取队头,删队头,考虑是否要在队尾插入元素! */ #include <bits/stdc++.h> using namespace std; const int N=55; int a[N][N];//存放地图 int vis[N][N];//vis[i][j]=1是访问过,vis[i][j]=0没访问过 //顺序DLRU下左右上 int dx[4]={1,0,0,-1};//行 int dy[4]={0,-1,1,0};//列 char f[4]={'D','L','R','U'}; struct point{ int x;int y;//当前点坐标(x,y) string ans;//到当前点的最短路径方案值 }; void bfs(){ queue<point>q; point w; w.x=1; w.y=1; q.push(w); while(q.size()){ //取队头弹出队头 point r=q.front(); // q.pop(); //打到最后一个点(30,50) if(r.x==30&&r.y==50){ cout<<r.ans; return ; } //从当前点r往下左右上走! for(int i=0;i<4;i++){ point t; t.x=r.x+dx[i]; t.y=r.y+dy[i]; t.ans=r.ans+f[i]; //vis是为了防止重复访问这个点这样就不最短,地图上0可以走 if(t.x>=1&&t.x<=30&&t.y>=1&&t.y<=50&&vis[t.x][t.y]==0&&a[t.x][t.y]==0){ vis[t.x][t.y]=1;//访问这个点 q.push(t); } } q.pop(); } } int main() { string s; for(int i=1;i<=30;i++){ cin>>s; for(int j=1;j<=50;j++){ a[i][j]=s[j-1]-'0'; } }
bfs(); // 请在此输入您的代码 return 0; }
F.特别数的和
考察:筛选
#include<bits/stdc++.h> using namespace std; typedef long long int ll; ll sum; int n; bool check(int a){ while(a){ int b=a%10; a/=10; if(b==2||b==0||b==1||b==9)return true; } return false; } int main(){ cin>>n; for(int i=1;i<=n;i++){ if(check(i))sum+=i; } cout<<sum; return 0; }G.完全二叉树的权值
考点:暴力枚举
//暴力枚举,因为最多10的5次方个结点那么一层的sum不可能超过10的10次方,所以用long long int #include<bits/stdc++.h> using namespace std; typedef long long int ll; int main(){ int n;//n个结点 ll sum;//每层的结点权值和 int maxi;//最大权值和的那层下标 ll maxs=-5e5;//先设定一个很小的值,每次看当前层是否要跟新最大权值和 int c=0;//存放当前层次,层次从1开始! int a;//当前结点值 cin>>n; for(int i=1;i<=n;i++){ cin>>a; if(i==pow(2,c)){//如果是每一层的第一个节点就跟新层次并将本层权值和归为0 sum=0;//当前层权值和归为0 c++; } sum+=a; //一层结束并且本层权值和>maxs就需要更新,注意完全二叉树可能最后一行放不满->此时结束条件i==n if(sum>maxs&&(i==pow(2,c)-1||i==n)){ maxs=sum; maxi=c; } } cout<<maxi; return 0; }H.等差数列
考察算法:最大公公因数gcd
思路:
现将数列从小到大排
然后相邻元素差值计算出来,并且求得差值的最大公因数作为数列的公差
最后根据an=a1 +(n-1)*d
所求的n=(an-a1)/d+1
#include <bits/stdc++.h> using namespace std; const int N=1e5+6; long long int A[N]; 最大公因数算法:gcd 当b不等于0返回一定要return gcd(b,a%b)否则返回a因为任何数都是0的因数int gcd(int a, int b) { return b?gcd(b,a%b):a; } int main() { int n; cin>>n; for(int i=0;i<n;i++)cin>>A[i]; sort(A,A+n); int d=A[1]-A[0]; if(d==0) { cout<<n; return 0; } for(int i=2;i<n;i++){ int p=A[i]-A[i-1]; d=gcd(d,p);//最大公因数stl中有内置函数__gcd( ) 注意是两个下划线横gcd() } cout<<((A[n-1]-A[0])/d)+1; // 请在此输入您的代码 return 0; }
I.后缀表达式
思路: 这题考察找规律 我们可以发现:后缀表达式与我们平常写的中缀表达式当二者要表达的意思一样时值一样,并且后缀表达式无括号相当于隐式括号。所以我们将这个问题转化为带括号的中缀最大值问题。 然后我们根据减号个数分类 1.没减号 那最值就是全加起来 2.有减号 就先让最大数减最小数,然后还剩n+m-1个数和n+m-1个符号,那就让他们任意搭配,如果搭配出来是负数就放在刚刚减最小数的括号里,如果是正数就直接加。 所以就是先最大减最小,让后其余全去正数。 完整代码如下:#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
int k=n+m+1;
int a[200010];
for(int i=0;i<k;i++)cin>>a[i];
sort(a,a+k);
long long int res=0;
if(!m){
for(int i=0;i<k;i++){
res+=a[i];
}
}
else{
res=a[k-1]-a[0];
for(int i=1;i<k-1;i++){
res+=abs(a[i]);
}
}
cout<<res;
// 请在此输入您的代码
return 0;
}
注意:数字个数是n+m+1,所以a[ ]的容量要大于200000
J.灵能传输
考前缀和+差分+找规律(难)#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 300010;
int n;
LL a[N], s[N];
bool st[N];
int main()
{
int T;
scanf("%d", &T);
while (T -- )
{
//每一组实验做一次前缀和
scanf("%d", &n);
s[0] = 0;
for (int i = 1; i <= n; i ++ )
{
scanf("%lld", &a[i]);
s[i] = s[i - 1] + a[i];
}
LL s0 = s[0], sn = s[n];//边界值
if (s0 > sn) swap(s0, sn);//为了统一为s0<sn,因为是对称的所以考虑一直情况即可。
sort(s, s + n + 1);//排序数组,0~n
//现在数列升序
//找寻s0第一次出现的下标值(因为按升序排列数组,原位置可能变动,因为s0可能等于sn,所以s0取前一个,sn取后一个。下面是确定他们的新下标。
for (int i = 0; i <= n; i ++ )
if (s[i] == s0)
{
s0 = i;
break;
}
for (int i = n; i >= 0; i -- )
if (s[i] == sn)
{
sn = i;
break;
}
memset(st, 0, sizeof st);
int l = 0, r = n;
//最前面一段
for (int i = s0; i >= 0; i -= 2)
{
a[l ++ ] = s[i];
st[i] = true;
}
//最后面一段
for (int i = sn; i <= n; i += 2)
{
a[r -- ] = s[i];
st[i] = true;
}
中间段(不重复走)
for (int i = 0; i <= n; i ++ )
if (!st[i])
a[l ++ ] = s[i];
LL res = 0;
for (int i = 1; i <= n; i ++ ) res = max(res, abs(a[i] - a[i - 1]));//存放结果准备好,所以最优选项就是当前这么摆,所以只有求相邻前缀和的差即求得当前数字值,然后取max的abs差值!
printf("%lld\n", res);//结果
}
return 0;
}