文章目录

  • 题目结构
  • 填空题
    • 第一题 空间
    • 第二题 卡片
    • 第三题 直线
    • 第四题 货物摆放
    • 第五题 路径
  • 程序题
    • 第六题 时间显示
    • 第七题 砝码称重
    • 第八题 杨辉三角形
    • 第九题 双向排序
    • 第十题 括号序列
  • 总结

题目结构

题目 类型 分值
第一题 结果填空 5分
第二题 结果填空 5分
第三题 结果填空 10分
第四题 结果填空 10分
第五题 结果填空 15分
第六题 程序设计 15分
第七题 程序设计 20分
第八题 程序设计 20分
第九题 程序设计 25分
第十题 程序设计 25分

填空题

第一题 空间

  • 问题描述

    小蓝准备用 256MB256MB256MB 的内存空间开一个数组,数组的每个元素都是 323232 位二进制整数,如果不考虑程序占用的空间和维护内存需要的辅助空间,请问256MB256MB256MB 的空间可以存储多少个 323232 位二进制整数?

  • 解题思路

    ​ 1MB=210KB=220B=220×8bit1MB=2^{10}KB=2^{20}B=2^{20}\times 8 bit1MB=210KB=220B=220×8bit。换算输出即可。

  • 答案

    671088646710886467108864


第二题 卡片

  • 问题描述

    小蓝有很多数字卡片,每张卡片上都是数字 000 到 999。小蓝准备用这些卡片来拼一些数,他想从 1 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。小蓝想知道自己能从 1 拼到多少。例如,当小蓝有 303030 张卡片,其中000 到 999 各 333 张,则小蓝可以拼出 1 到 10,但是拼 11 时卡片 1 已经只有一张了,不够拼出 11。现在小蓝手里有 0 到 9 的卡片各 202120212021 张,共 202102021020210 张,请问小蓝可以从 111拼到多少?提示:建议使用计算机编程解决问题。

  • 解题思路

    直接模拟到用完为止,注意细节,最后退出的数需要减111,因为我们拼不成。

  • 代码

/***@filename:B*@author: pursuit*@CSDNBlog:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-04-18 14:37
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;int n;
int a[10];
bool work(int x){while(x){int temp=x%10;x/=10;if(a[temp]>0){a[temp]--;}else{return false;}}return true;
}
int main(){while(cin>>n){for(int i=0;i<=9;i++)a[i]=n;int cnt=1;while(true){if(work(cnt)){cnt++;}else{break;}}cout<<cnt-1<<endl;//注意减1.//3181}return 0;
}
  • 答案

    318131813181


第三题 直线

  • 问题描述

    在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。给定平面上 2×32 × 32×3个整点 (x,y)∣0≤x<2,0≤y<3,x∈Z,y∈Z{(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x∈ Z, y ∈ Z}(x,y)∣0≤x<2,0≤y<3,x∈Z,y∈Z,即横坐标是 0 到 1 (包含 0 和 1) 之间的整数、纵坐标是 000 到 222 (包含 000 和222) 之间的整数的点。这些点一共确定了 11 条不同的直线。给定平面上 20 × 21 个整点 (x,y)∣0≤x<20,0≤y<21,x∈Z,y∈Z{(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z}(x,y)∣0≤x<20,0≤y<21,x∈Z,y∈Z,即横坐标是 000 到 191919 (包含 000 和 191919) 之间的整数、纵坐标是 0 到 20 (包含000 和 202020) 之间的整数的点。请问这些点一共确定了多少条不同的直线。

  • 解题思路

    写错了,以为是找规律,比赛的时候推的公式为n+m+(n−1)∗n/2∗(m−1)∗m/2∗2n+m+(n-1)*n/2*(m-1)*m/2*2n+m+(n−1)∗n/2∗(m−1)∗m/2∗2。正确解法利用直线判重解决这道题,表示直线的方式有很多种,这里采用斜截式来表示,通set容器来判重。需要注意的一个细节就是需要避免k=0k=0k=0和k=infk=infk=inf的情况。 具体看代码。

  • 代码

/***@filename:C*@author: pursuit*@CSDNBlog:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-04-18 14:40
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;int n,m;
struct Point{int x,y;Point(){}Point(int x,int y){this->x=x,this->y=y;}
};
struct Line{//我们通过点斜式来确定一条直线,即y=kx+b;那么判重的方法就是判断k和b是不是相等的。double k,b;Line(){}Line(double k,double b){this->k=k,this->b=b;}//由于我们要利用set判重,故我们需要对<运算符重载。bool operator<(const Line &A)const {if(k==A.k)return b<A.b;return k<A.k;}
};
set<Line> t;
Point points[maxn];
int cnt=0;//点的个数。
void addLine(Point a1,Point a2){if(a1.x==a2.x||a1.y==a2.y)return;//对于k=0,或者k=无穷的情况我们不考虑,避免精度损失等问题。最后我们累加上这些即可。n+m。double temp=(a2.x-a1.x)*1.0;double k=(a2.y-a1.y)*1.0/temp;double b=(a1.y*a2.x-a1.x*a2.y)*1.0/temp;t.insert(Line(k,b));
}
int main(){cin>>n>>m;for(int i=0;i<n;i++){for(int j=0;j<m;j++){points[cnt++]=Point(i,j);}}//接下来确定直线加入set中。for(int i=0;i<cnt;i++){for(int j=0;j<cnt;j++){addLine(points[i],points[j]);}}cout<<t.size()+n+m<<endl;return 0;
}
  • 答案

    402574025740257

第四题 货物摆放

  • 问题描述

    小蓝有一个超大的仓库,可以摆放很多货物。现在,小蓝有 n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。小蓝希望所有的货物最终摆成一个大的立方体。即在长、宽、高的方向上分别堆 L、W、HL、W、HL、W、H 的货物,满足 n=L×W×Hn = L × W × Hn=L×W×H。给定 n,请问有多少种堆放货物的方案满足要求。例如,当 n=4n = 4n=4 时,有以下 6 种方案:1×1×4、1×2×2、1×4×1、2×1×2、2×2×1、4×1×11×1×4、1×2×2、1×4×1、2×1×2、 2 × 2 × 1、4 × 1 × 11×1×4、1×2×2、1×4×1、2×1×2、2×2×1、4×1×1。请问,当 n=2021041820210418n = 2021041820210418n=2021041820210418(注意有 161616 位数字)时,总共有多少种方案?提示:建议使用计算机编程解决问题。

  • 解题思路

    枚举因子,由于不同顺序是不同的方案,所以我们先要假定i≤j≤ki\leq j \leq ki≤j≤k,然后最后我们就可以对i,j,ki,j,ki,j,k排列了,这样所有的情况都会被考虑,而因为都不相同的时候是666种排列,有且只有两个相同的时候是333种排列,都相同的时候是一种排列。所以我们需要统计满足条件的数目cnt0cnt0cnt0、满足条件的数目且其中有且仅有两个相同的数目cnt1cnt1cnt1、满足条件的数目有且仅有三个相同的数目cnt2cnt2cnt2。最后答案即是cnt0×6−cnt1×3−cnt2×5cnt0\times 6-cnt1\times 3 - cnt2\times 5cnt0×6−cnt1×3−cnt2×5。

  • 代码

/***@filename:B*@author: pursuit*@CSDNBlog:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-04-18 14:28
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;ll n;
void solve(){}
int main(){while(cin>>n){int cnt0=0,cnt1=0,cnt2=0;//cnt0统计所有情况,cnt1统计两个数相等的情况,cnt2统计三个数相等的情况for(ll i=1;i*i*i<=n;i++){if(n%i)continue;for(ll j=i;i*j*j<=n;j++){if(n%j)continue;ll k=n/(i*j);if(i*j*k==n){cnt0++;if(i==j&&j==k){cnt2++;}else if(i==j||j==k||i==k){cnt1++;}}}}cout<<cnt0<<" "<<cnt1<<" "<<cnt2<<endl;//406 2 0//不相等6种排列,只有两个相等三种排列,三个相等一种排列。cout<<cnt0*6-cnt1*3-cnt2*5<<endl;//2430}solve();return 0;
}
  • 答案

    243024302430


第五题 路径

  • 问题描述

    小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。小蓝的图由 202120212021 个结点组成,依次编号 111 至 202120212021。对于两个不同的结点 a,ba, ba,b,如果 aaa 和 bbb 的差的绝对值大于 212121,则两个结点之间没有边相连;如果 aaa 和 bbb 的差的绝对值小于等于 212121,则两个点之间有一条长度为 aaa 和 bbb 的最小公倍数的无向边相连。例如:结点 111 和结点 232323 之间没有边相连;结点 333 和结点 242424 之间有一条无向边,长度为 242424;结点 151515 和结点 252525 之间有一条无向边,长度为 757575。请计算,结点 111 和结点 202120212021 之间的最短路径长度是多少。提示:建议使用计算机编程解决问题。

  • 解题思路

    最短路模板题。本题我采用dijkstradijkstradijkstra算法实现的。

  • 代码

/***@filename:E*@author: pursuit*@CSDNBlog:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-04-18 14:50
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 10000 + 5;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;//最短路板子题。
int n;
int g[maxn][maxn];
int dist[maxn];
bool vis[maxn];
int gcd(int n,int m){return n%m?gcd(m,n%m):m;
}
void init(){memset(vis,0,sizeof(vis));for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){if(abs(i-j)<=21){g[i][j]=g[j][i]=i*j/gcd(i,j);}else{g[i][j]=g[j][i]=inf;}}}
}
void dijkstra(int st){for(int i=1;i<=n;i++){dist[i]=g[st][i];}vis[st]=true;for(int i=1;i<=n;i++){int minn=inf,index;for(int j=1;j<=n;j++){if(!vis[j]&&dist[j]<minn){minn=dist[j];index=j;}}if(minn==inf)break;vis[index]=true;for(int j=1;j<=n;j++){if(!vis[j]&&dist[j]>dist[index]+g[index][j]){dist[j]=dist[index]+g[index][j];}}}cout<<dist[n]<<endl;//n=2021 print:10266837
}
void solve(){init();dijkstra(1);
}
int main(){while(cin>>n){solve();}return 0;
}
  • 答案

    102668371026683710266837

程序题

第六题 时间显示

  • 问题描述

    小蓝要和朋友合作开发一个时间显示的网站。在服务器上,朋友已经获取了当前的时间,用一个整数表示,值为从197019701970 年 111 月 111 日 00:00:0000:00:0000:00:00到当前时刻经过的毫秒数。现在,小蓝要在客户端显示出这个时间。小蓝不用显示出年月日,只需要显示出时分秒即可,毫秒也不用显示,直接舍去即可。给定一个用整数表示的时间,请将这个时间对应的时分秒输出。

    【输入格式】

    输入一行包含一个整数,表示时间。

    【输出格式】

    输出时分秒表示的当前时间,格式形如 HH:MM:SSHH:MM:SSHH:MM:SS,其中 HHHHHH 表示时,值为 000 到232323,MMMMMM 表示分,值为 000 到 595959,SSSSSS 表示秒,值为 000 到 595959。时、分、秒

    不足两位时补前导 000。

    【样例输入 1】

    468009994680099946800999

    【样例输出 1】

    13:00:0013:00:0013:00:00

    【样例输入 2】

    161870810312316187081031231618708103123

    【样例输出 2】

    01:08:2301:08:2301:08:23

    【评测用例规模与约定】

    对于所有评测用例,给定的时间为不超过 1018 的正整数。

  • 解题思路

    水题,转换时间。注意:1s=1000ms1s=1000ms1s=1000ms。

  • AC代码

/***@filename:F*@author: pursuit*@CSDNBlog:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-04-18 14:57
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;ll n;
void solve(){n/=1000;printf("%02d:%02d:%02d\n",(n%(24*3600))/3600,n%3600/60,n%60);
}
int main(){while(cin>>n){solve();}return 0;
}

第七题 砝码称重

  • 问题描述

    你有一架天平和 NNN 个砝码,这 NNN个砝码重量依次是 W1,W2,⋅⋅⋅,WNW_1, W_2, · · · , W_NW1​,W2​,⋅⋅⋅,WN​。请你计算一共可以称出多少种不同的重量?注意砝码可以放在天平两边。

    【输入格式】

    输入的第一行包含一个整数 NNN。

    第二行包含 NNN 个整数:W1,W2,W3,⋅⋅⋅,WNW_1, W_2, W_3, · · · , W_NW1​,W2​,W3​,⋅⋅⋅,WN​。

    【输出格式】

    输出一个整数代表答案。

    【样例输入】

    3

    1 4 6

    【样例输出】

    10

    【样例说明】

    能称出的 10 种重量是:1、2、3、4、5、6、7、9、10、11。

    1 = 1;

    2 = 6 − 4 (天平一边放 6,另一边放 4);

    3 = 4 − 1;

    4 = 4;

    5 = 6 − 1;

    6 = 6;

    7 = 1 + 6;

    9 = 4 + 6 − 1;

    10 = 4 + 6;

    11 = 1 + 4 + 6。

    【评测用例规模与约定】

    对于 50% 的评测用例,1≤N≤151 ≤ N≤ 151≤N≤15。

    对于所有评测用例,1≤N≤1001 ≤ N ≤ 1001≤N≤100,NNN 个砝码总重不超过 100000100000100000。

  • 解题思路

    我们可以先来定义一下,我们总认为称出的重量为左边减右边,也就是说如果要增加就放左边,如果要减少就放右边,否则不放。

    这种决策问题一看就是dpdpdp了,然而比赛的时候也还是不知道该怎么处理,于是用dfs枚举。能过一半的样例。
    补题:看了大佬的写法,确实是背包问题的变种,三种决策,不过这个题我们不是用maxmaxmax来判断,因为我们只关心能否凑成,所以只需要累加之前的状态即可。

  • dfsdfsdfs捡分代码

/***@filename:G*@author: pursuit*@CSDNBlog:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-04-18 15:15
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;//
int n;
int w[maxn];
int cnt[maxn];
int sum;
void dfs(int step,int ans){//step表示当前正在选择的砝码,ans为左边减右边的重量。if(step==n+1){//说明前n个已经选完了。if(ans<=0)return;cnt[ans]++;return;}dfs(step+1,ans+w[step]);//放左边。dfs(step+1,ans);//不放。dfs(step+1,ans-w[step]);//放右边。
}
void solve(){dfs(1,0);int ans=0;for(int i=1;i<=sum;i++){if(cnt[i]>0)ans++;}cout<<ans<<endl;
}
int main(){cin>>n;sum=0;for(int i=1;i<=n;i++){cin>>w[i];sum+=w[i];}solve();return 0;
}
  • 动态规划解题代码

/***@filename:G砝码称重背包问题变种*@author: pursuit*@CSDNBlog:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-04-19 18:55
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;//背包dp。累加三种方案数即可。
int n;
int w[105];
int dp[105][maxn<<2];//dp[i][j]表示的即是前i个砝码中能凑成重量j的方案数。
int main(){cin>>n;for(int i=1;i<=n;i++)cin>>w[i];//由于我们在进行决策的时候会出现负数,所以我们需要将数组进行偏移一个maxn确保枚举的时候不会出现错误。dp[0][maxn]=1;//注意设立起始值作为更新点。for(int i=1;i<=n;i++){for(int j=-maxn+w[i];j<=maxn;j++){//从小到大开始枚举。//不选,加上,减去三种决策。dp[i][j+maxn]=dp[i-1][j+maxn]+dp[i-1][j+maxn+w[i]]+dp[i-1][j+maxn-w[i]];}}int ans=0;//累加所有出现的状态。for(int j=maxn+1;j<=maxn*2;j++){if(dp[n][j])ans++;}cout<<ans<<endl;return 0;
}

第八题 杨辉三角形

  • 问题描述

    下面的图形是著名的杨辉三角形:

    如果我们按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:

    1,1,1,1,2,1,1,3,3,1,1,4,6,4,1,...1, 1, 1, 1, 2, 1, 1, 3, 3, 1, 1, 4, 6, 4, 1, ...1,1,1,1,2,1,1,3,3,1,1,4,6,4,1,...

    给定一个正整数 NNN,请你输出数列中第一次出现 NNN 是在第几个数?

    【输入格式】

    输入一个整数 N。N。N。

    【输出格式】

    输出一个整数代表答案。

    【样例输入】

    6

    【样例输出】

    13

    【评测用例规模与约定】

    对于 20% 的评测用例,1≤N≤101 ≤ N≤ 101≤N≤10;

    对于所有评测用例,1≤N≤10000000001 ≤N ≤ 10000000001≤N≤1000000000。

  • 解题思路

    杨辉三角第iii行第jjj列的数为Ci−1j−1C_{i-1}^{j-1}Ci−1j−1​,那么我们直接枚举i,ji,ji,j即可。不过有一个坑点,比赛的时候没想到,就是Cn1C_{n}^1Cn1​的时候,需要枚举O(n2)O(n^2)O(n2),没有想到。哎,只能过的20%20\%20%的分。

  • 偷分代码

/***@filename:H*@author: pursuit*@CSDNBlog:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-04-18 15:00
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;ll C(ll n,ll m){ll ans=1;for(ll i=n,j=1;i>=(n-m+1);i--,j++){ans=ans*i/j;}return ans;
}
ll n;
void solve(){if(n==1){cout<<1<<endl;return;}bool flag=false;for(ll i=3;;i++){for(ll j=1;j<i;j++){if(C(i-1,j)==n){flag=true;cout<<(i-1)*i/2+j+1<<endl;//不过好像没考虑n特别大的时候。。。即跑1e9*1e9跑不出。break;}}if(flag)break;}
}
int main(){while(cin>>n){solve();}return 0;
}
  • 标程
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int n;
LL C(int a, int b)   //计算C(a,b)
{LL res = 1;for(int i = a, j = 1; j <= b; i --, j ++){res = res * i / j;if(res > n)return res;     // 大于n已无意义,且防止爆LL}return res;
}
bool check(int k)
{// 二分该斜行,找到大于等于该值的第一个数// 左边界2k,右边界为max(l, n)取二者最大,避免右边界小于左边界int l = 2 * k, r = max(n,l);while(l < r){int mid = l + r >> 1;if(C(mid, k) >= n) r = mid;else l = mid + 1;}if(C(r, k) != n)return false;cout << 1ll*(r + 1) * r / 2 + k + 1 << endl;return true;
}
int main()
{cin >> n;// 从第16斜行枚举for(int i = 16; ; i--)if(check(i))break;return 0;
}

第九题 双向排序

  • 问题描述

    给定序列 (a1,a2,⋅⋅⋅,an)=(1,2,⋅⋅⋅,n)a_1, a_2, · · · , a_n) = (1, 2, · · · , n)a1​,a2​,⋅⋅⋅,an​)=(1,2,⋅⋅⋅,n),即 ai=ia_i = iai​=i。小蓝将对这个序列进行 mmm 次操作,每次可能是将 a1,a2,⋅⋅⋅,aqia_1, a_2, · · · , a_{q_i}a1​,a2​,⋅⋅⋅,aqi​​ 降序排列,或者将aqi,aqi+1,⋅⋅⋅,ana_{q_i},a_{q_{i+1}}, ···,a_naqi​​,aqi+1​​,⋅⋅⋅,an​ 升序排列。请求出操作完成后的序列。

    【输入格式】

    输入的第一行包含两个整数 n,mn, mn,m,分别表示序列的长度和操作次数。

    接下来 mmm 行描述对序列的操作,其中第 iii 行包含两个整数 pi,qip_i, q_{i}pi​,qi​ 表示操作类型和参数。当 pip_ipi​ = 0 时,表示将 a1,a2,⋅⋅⋅,aqia_1, a_2, · · · , a_{q_i}a1​,a2​,⋅⋅⋅,aqi​​ 降序排列;当 pi=1p_i = 1pi​=1 时,表示将 aqi,aqi+1,⋅⋅⋅,ana_{q_i} , a_{q_{i+1}}, · · · , a_naqi​​,aqi+1​​,⋅⋅⋅,an​ 升序排列。

    【输出格式】
    输出一行,包含 nnn 个整数,相邻的整数之间使用一个空格分隔,表示操作完成后的序列。

    【样例输入】

    3 3

    0 3

    1 2

    0 2

    【样例输出】

    3 1 2

    【样例说明】

    原数列为 (1, 2, 3)。

    第 1 步后为 (3, 2, 1)。

    第 2 步后为 (3, 1, 2)。

    第 3 步后为 (3, 1, 2)。与第 2 步操作后相同,因为前两个数已经是降序了。

    【评测用例规模与约定】

    对于 30% 的评测用例,n,m≤1000n, m ≤ 1000n,m≤1000;

    对于 60% 的评测用例,n,m≤5000n, m ≤ 5000n,m≤5000;

    对于所有评测用例,1≤n,m≤100000,0≤pi≤1,1≤qi≤n1 ≤ n, m ≤ 100000,0 ≤ p_i ≤ 1,1 ≤ q_i ≤ n1≤n,m≤100000,0≤pi​≤1,1≤qi​≤n。

  • 解题思路

    有点线段树的味道,但不知道怎么处理,所以只能暴力出奇迹了,能过60%60\%60%的数据。

  • 偷分代码

/***@filename:I*@author: pursuit*@CSDNBlog:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-04-18 15:58
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;int n,m;
int main(){while(cin>>n>>m){vector<int> a(n);for(int i=0;i<n;i++)a[i]=i+1;int p,q;while(m--){cin>>p>>q;if(p)sort(a.begin()+q-1,a.end());else sort(a.begin(),a.begin()+q,greater<int>() );}for(int i=0;i<n;i++){cout<<a[i];i==n-1?cout<<endl:cout<<" ";}}return 0;
}
  • 标程
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
PII s[100005];
int n,m;
int top;
int ans[100005];
int main() {cin>>n>>m;int x,y;for(int i=1; i<=m; ++i) {scanf("%d%d",&x,&y);if(!x)//0操作 {if(top&&s[top].first==0) {//对于连续的0操作只保留一个 y=max(y,s[top--].second);}while(top>=2&&s[top-1].second<=y) {//0操作覆盖掉乱序区 top-=2;}s[++top]= make_pair(0,y);//插入 }else if(top)//栈不为空,且为1操作。{//因为是0/1是交替出现的,且只会有一个,所以这里取最小值即可。 if(top&&s[top].first==1) {y=min(y,s[top--].second);}while(top>=2&&s[top-1].second>=y) {top-=2;}s[++top]= make_pair(1,y);}}int k=n,l=1,r=n;for(int i=1; i<=top; ++i) {//将固定的数字插入ans数组里 if(s[i].first==0) {while(r>s[i].second&&l<=r) ans[r--]=k--;} else {while(l<s[i].second&&l<=r) ans[l++]=k--;}if(l>r) break;}//如果有数字没被固定,就还需要将它们存入ans数组里 if(top%2!=0) {while(k>0) ans[l++]=k--;} else {while(k>0) ans[r--]=k--;}for(int i=1;i<=n;++i){printf("%d ",ans[i]);}return 0;
}

第十题 括号序列

  • 问题描述

    给定一个括号序列,要求尽可能少地添加若干括号使得括号序列变得合法,当添加完成后,会产生不同的添加结果,请问有多少种本质不同的添加结果。两个结果是本质不同的是指存在某个位置一个结果是左括号,而另一个是右括号。例如,对于括号序列 (((),只需要添加两个括号就能让其合法,有以下几种不同的添加结果:()()()、()(())、(())()、(()()) 和 ((()))。

    【输入格式】

    输入一行包含一个字符串 sss,表示给定的括号序列,序列中只有左括号和右括号。

    【输出格式】

    输出一个整数表示答案,答案可能很大,请输出答案除以 100000000710000000071000000007(即109+710^9 + 7109+7) 的余数。

    【样例输入】

    ((()

    【样例输出】

    5

    【评测用例规模与约定】

    对于 40% 的评测用例,∣s∣≤200|s| ≤ 200∣s∣≤200。

    对于所有评测用例,1≤∣s∣≤50001 ≤ |s| ≤ 50001≤∣s∣≤5000。

  • 解题思路
    指路一篇blog:括号序列

  • 代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
const int maxn = 5000 + 5;
const int mod = 1e9 + 7;
int n;
int dp[maxn][maxn];
string a ;
ll calc ()
{memset(dp , 0 , sizeof dp);dp[0][0] = 1;for (int i = 1 ; i <= n ; i++){if (a[i - 1] == '('){for (int j = 1 ; j <= n ; j++)dp[i][j] = dp[i - 1][j - 1];}else {dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) % mod;for (int j = 1 ; j <= n ; j++)dp[i][j] = (dp[i - 1][j + 1] + dp[i][j - 1]) % mod;}}for (int i = 0 ; i <= n ; i++) if (dp[n][i]) return dp[n][i];return -1;
}
int main()
{ios::sync_with_stdio(false);cin >> a;n = a.size();ll l = calc();reverse(a.begin() , a.end());for (auto &g : a) if (g == '(') g = ')'; else g = '(';ll r = calc();cout << l * r % mod << endl;return 0;
}

总结

难度适中,梯度明显,整体还算OK,待结果出来还愿。希望能取得一个不错的结果。

来还愿了:一等奖,排名还靠前。
再次还愿:总决赛二等奖。

2021年4月 第十二届蓝桥杯软件类省赛C++B组第一场 真题题解相关推荐

  1. 2021年第十二届蓝桥杯软件类省赛python组试题及其解析。

    目录 一.卡片 二.直线 三.货物摆放 四.路径 五.回路计算 六.时间显示 七.杨辉三角 八.左孩子右兄弟 九.异或数列 十.括号序列 一.卡片 本题总分:5分 [问题描述] 小蓝有很多数字卡片,每 ...

  2. 2021年第十二届蓝桥杯软件类省赛python组

    目录 2021年第十二届蓝桥杯软件类省赛python组 1.卡片 常规做法 使用functions.Counter计数 2.直线 3.货物摆放 4.路径 5.回路计算 递归--太慢跑不出来 状态压缩D ...

  3. 第十二届蓝桥杯软件类模拟赛python程序设计 第二期(6)平行四边形面积

    如有错误欢迎指正 如有更好的解法欢迎分享 Topic 问题描述 给定一个平行四边形的底边长度 l 和高度 h,求平行四边形的面积. 输入格式 输入的第一行包含一个整数 l,表示平行四边形的底边长度. ...

  4. 蓝桥杯|2021第十二届蓝桥杯第二次模拟赛真题与解答[Java]

    记录2021年第十二届蓝桥杯第二次模拟赛真题与解题,部分答案来自网络.个人记录,菜得很. 目录 填空题 一 二 三 四 五 编程题 六 七 八 九 十 填空题 一 问题描述 请问在 1 到 2020 ...

  5. 砝码称重【第十二届蓝桥杯】【省赛】【B组】

    砝码称重[第十二届蓝桥杯][省赛][B组] Description 你有一架天平和N个砝码,这N个砝码重量依次是W1.W2,-WN 请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边. ...

  6. 五邑大学校级蓝桥杯c语言试题,【智能制造学部】第十届“蓝桥杯”软件类校内选拔赛顺利举行...

    11月24日上午,由国家工业和信息化部.人才交流中心主办,共青团五邑大学委员会.五邑大学学生会协办,智能制造学部承办的第十届"蓝桥杯"全国软件和信息技术专业人才大赛软件类校内选拔赛 ...

  7. 2022年4月蓝桥杯软件类省赛:真题+解析

    文章目录 试题 A 试题 B 试题 C 试题 D 试题 E 试题 F 试题 G 试题 H 试题 I 试题 J 相关文章: 2021年4月蓝桥杯(软件类)省赛:真题+解析 2020年10月蓝桥杯(软件类 ...

  8. 第十二届蓝桥杯大赛个人赛省赛(软件类)真题-Java语言B组

    目录 1.ASC 2.卡片 3.直线 4.货物摆放 5.路径 6.时间显示 7.最少砝码 8.杨辉三角形 9.双向排序 10.括号序列 1.ASC [问题描述] 已知大写字母 A 的 ASCII 码为 ...

  9. 第十二届蓝桥杯第二期模拟赛(java) python解法

    A 问题描述 小明要用二进制来表示 1 到 10000 的所有整数,要求不同的整数用不同的二进制数表示,请问,为了表示 1 到 10000 的所有整数,至少需要多少个二进制位? 结果:14 print ...

最新文章

  1. Word无法打开该文件,因为文件格式与文件扩展名不匹配的解决办法
  2. Python之tkinter:动态演示调用python库的tkinter带你进入GUI世界(LabelFrame/Checkbutton/Radiobutton)
  3. find_in_set()和in()比较
  4. php win2003 下载,64位windows2003iis安装包|《win2003 iis安装包》64位完整版附安装PHP教材...
  5. BSP技术详解3---有图有真相
  6. 常见的网络工程师面试问题
  7. 【ArcGIS遇上Python】长时间序列(30年)每两组栅格数据对应做减法运算求物候参数
  8. android 录音原始文件_音频采集:Android基于AudioRecord的实现
  9. 3.5 卷积神经网络进阶-Inception-mobile_net 实战
  10. css清除浮动的集中方法
  11. Theano 中文文档 0.9 - 7.2.6 Theano如何处理形状信息
  12. linux 查询wwid命令,Linux磁盘及分区之wwid和uuid
  13. 什么是base64?
  14. python二进制转十进制编程_怎么用python二进制转换十进制
  15. k60的FTM模块:配置电机、编码器、舵机
  16. Markdown数学公式语法、常用符号与字体
  17. node.js —— express中的next( )
  18. 基于springboot特色农产品电商平台毕业设计-附源码211515
  19. c语音大小写字母转换
  20. win10怎么用计算机的搜索,win10搜索文件内容怎么操作_win10如何搜索文档内的内容...

热门文章

  1. 钱诚10.28外汇黄金价格投资策略、美原油最新价格布局及指导
  2. Java内置线程池ExecutorService介绍及商品秒杀案例
  3. TCP/IP协议卷学习---基础部分(十五 TFTP)
  4. 银行智能案防:以“AI技防”堵住违规漏洞
  5. Trie 树:如何实现搜索引擎的搜索关键词提示功能
  6. execute、executeUpdate、executeQuery三者的区别(及返回值)
  7. 微信小程序如何获取用户头像昵称
  8. Matlab批量拟合曲线并绘制在一张图上
  9. 2010年度总结3:GIS导航软件项目
  10. 粉丝裂变这么简单,99%的人都不知道