2023 PTA天梯赛补题(L1 & L2)
2023 天梯赛 L1 & L2 补题
L1
L1-089 最好的文档
输入输出题
#include<bits/stdc++.h> using namespace std; int main() { cout<<"Good code is its own best documentation."; return 0; }
L1-090 什么是机器学习
输入输出题
#include<bits/stdc++.h> using namespace std; int main() { int a,b; cin>>a>>b; int c = a + b; cout<<c-16<<endl; cout<<c-3<<endl; cout<<c-1<<endl; cout<<c; return 0; }
L1-091 程序员买包子
k == n 和 k == m 分别输出,题目怎么说就怎么做
#include<bits/stdc++.h> using namespace std; int main() { int n,m,k; string s; cin>>n>>s>>m>>k; if(k == n) cout<<"mei you mai "<<s<<" de"; else if(k == m) cout<<"kan dao le mai "<<s<<" de"; else cout<<"wang le zhao mai "<<s<<" de"; return 0; }
L1-092 进化论
判断一下c 等于a + b还是a*b或者都不是,分别按要求输出
#include<bits/stdc++.h> using namespace std; int main() { int n; cin>>n; for(int i = 1;i <= n;i++) { int a,b,c; cin>>a>>b>>c; if(c == a + b) cout<<"Tu Dou"; else if(c == a*b)cout<<"Lv Yan"; else cout<<"zhe du shi sha ya!"; if(i != n) cout<<endl; } return 0; }
L1-093 猜帽子游戏
针对每一群玩游戏的宝宝,枚举判断一下就好了
#include<bits/stdc++.h> using namespace std; const int N = 1e5; int f[N]; int n; int main() { cin>>n; for(int i = 1;i <= n;i++) cin>>f[i]; int t; cin>>t; for(int j = 1;j <= t;j++) { int cnt = 0; bool flag = true; for(int i = 1;i <= n;i++) { int x;cin>>x; if(x == 0) continue; if(x == f[i]) cnt++; else flag = false; } if(flag&&cnt) cout<<"Da Jiang!!!"; else cout<<"Ai Ya"; if(t != j) cout<<endl; } return 0; }
L1-094 剪切粘贴
写的有点烦,基本就是一步一步模拟,思路在注释里写了
#include<bits/stdc++.h> using namespace std; int n; int main() { string s; cin>>s>>n; for(int i = 1;i <= n;i++) { int a,b; string s1,s2; cin>>a>>b>>s1>>s2; a -= 1; //保证下标从0开始 b -= 1; //剪切 string t = s.substr(a,b-a+1); //剪切出的字符串 string sbe = s.substr(0,a); //t前面的字符串 string saf = s.substr(b+1,s.size() - b - 1);//t后面的字符串 s = sbe+saf; //剪切后的串 //粘贴 int len1 = s1.size(); int len2 = s2.size(); int st = -1; for(int j = 0;j + len1 - 1 < s.size();j++) { //查找开头与s1相同的串 string temp = s.substr(j,len1); if(temp == s1) { st = j;//存下标 //查看是否以s2结尾 string af = s.substr(st+len1,len2); if(af == s2) { //粘贴操作 string ss1 = s.substr(0,st+len1); string ss2 = s.substr(st+len1,s.size()); s = ss1 + t + ss2; break; } else{ st = -1; } } } //没有满足条件的粘贴位置,粘贴在最后 if(st == -1) s = s + t; } cout<<s; return 0; }
L1-095 分寝室
枚举分配方案,代码中a代表女生寝室的数量,b为男生寝室的数量,如果存在寝室人数差值小于之前的最小值,则更新a,b,最后输出a和b即可
#include<bits/stdc++.h> using namespace std; using ll = long long; int a,b; int main() { int n0,n1,n; cin>>n0>>n1>>n; int st = 1e9; for(int i = 1;i <= n-1;i++) { if((n0 % i == 0) && (n1 %(n-i) == 0)) { int x = n0/i,y = n1/(n-i); if(x == 1 || y == 1) continue; if(abs(x-y) < st) { st = abs(x-y); a = i,b = n-i; } } } if(st != 1e9) cout<<a<<" "<<b; else cout<<"No Solution"; return 0; }
L1-096 谁管谁叫爹
模拟,要注意
如果 NA正好是 SB的整数倍,则 A 是爹;如果 NB正好是 SA的整数倍,则 B 是爹;
这里是NA是SB的整数倍,写的时候要小心,容易看错。
#include<bits/stdc++.h> using namespace std; using ll = long long; ll get(ll n) { ll res = 0; while(n) { res += n % 10; n /= 10; } return res; } int main() { int n; cin>>n; for(int i = 1;i <= n;i++) { ll a,b; cin>>a>>b; ll sa = get(a); ll sb = get(b); if(!(a % sb) && (b % sa)) cout<<"A"; else if(!(b % sa) && (a % sb)) cout<<"B"; else{ if(a > b) cout<<"A"; else cout<<"B"; } if(i != n) cout<<"\n"; } return 0; }
L2
L2-045 堆宝塔
题目怎么说就怎么做,这里用数组模拟栈,用起来更舒服一些,个人觉得比STL好用
#include<bits/stdc++.h> using namespace std; const int N = 10100; int cnt,high; int va[N],pa; int vb[N],pb; int main() { int n; cin>>n; for(int i = 1;i <= n;i++) { int x; cin>>x; if(pa == 0) va[pa++] = x; else { if(va[pa-1] > x) va[pa++] = x; else { if(pb == 0 || x > vb[pb-1]) vb[pb++] = x; else { cnt ++; high = max(high,pa); pa = 0; while(pb) { if(vb[pb-1] > x) { va[pa++] = vb[--pb]; } else break; } va[pa++] = x; } } } } if(pa) { cnt++; high = max(high,pa); } if(pb) { cnt++; high = max(high,pb); } cout<<cnt<<" "<<high; return 0; }
L2-046 天梯赛的赛场安排
纯暴力写法用结构体排序 ,然后会收获两个TLE,只能得18分
这题要用优先队列去优化这个排序过程,优先队列底层用堆实现的,大根堆就是从大到小排序,小根堆是从小到大排序,默认是大根堆,所有本题直接用默认就好了。
sort排序最快也要O(nlogn),使用优先队列将一个无序序列调整成有序序列只需要O(n),并且向堆中加入元素,只需要O(logn),这大大降低这道题的时间复杂度。
其次这题可以直接先将各个大学可以分配的考场先计算出来,如果某个大学参赛人数刚好是c的整数倍,那么他已经分配好了不用加入优先队列中。
#include<bits/stdc++.h> using namespace std; #define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); const int INF = 0x3f3f3f3f,mod = 1000000007; using ll = long long; int T; const int N = 5010; struct Node{ string name; int num;//未安排人数 //运算符重载 bool operator < (const Node &s) const { return num < s.num; } }f[N]; int n,c; int cnt; map<string,int>mp; string order[N]; inline void run() { cin>>n>>c; priority_queue<Node>q;//默认大根堆 for(int i = 1;i <= n;i++) { string name;int num; cin>>name>>num; order[i] = name; int cls = num / c; cnt += cls; num = num - cls * c; if(num != 0) q.push({name,num}); mp[name] = cls; } vector<int>cls; while (q.size()) { auto t = q.top(); q.pop(); string name = t.name; int num = t.num; bool flag = false; for(int j = 0;j < cls.size();j++) { if((c - cls[j]) >= num) { cls[j] += num; mp[name] += 1; flag = true; break; } } if(!flag) { cnt++; cls.push_back(num); mp[name] += 1; } } for(int i = 1;i <= n;i++) cout<<order[i]<<" "<<mp[order[i]]<<endl; cout<<cnt; } int main() { IOS; // cin>>T; // while (T--) // run(); run(); return 0; }
L2-047 锦标赛
败者树的模型,常见的是胜者树,这题就是给出败者树,然后需要还原原序列,虽然我知道要这么做,但是还是没写出来/(ㄒoㄒ)/~~,下面的代码是另一位博主的,原代码链接点这。
大体思路如下:
每次我们都可以完善数组的一半,然后剩下一半
完善的过程:
对于第一层,是第一次比赛的结果,相邻两个进行比较的结果,因此,我们可以把第一层第i个数的位置放在原始数组i*2-1中
对于接下来的几层,它能加入原始数组的条件就是 它的数值不小于前一层两个对应位置分别的所组成子树的最大值 否则它将无法加入到原始数组中去
为了实现构造还要建立一个数组,来记录该位置的一下位置在哪里
#include<bits/stdc++.h> using namespace std; #define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); const int INF = 0x3f3f3f3f,mod = 1000000007; using ll = long long; const int N = 20,M = (1 << 19); int T; int k; int ans[M];//结果数组 int a[N][M],id[N][M];//a数组存储输入的数据,id存储还能放数的空余位置 inline void run() { cin>>k; int flag = 1,max1; for(int i = 1;i <= k;i++){ for(int j = 1;j <= (1<<(k-i));j++){ cin>>a[i][j]; if(i == 1) ans[j*2-1]=a[i][j],id[i][j]=j*2; //loser放在左儿子,winner放在右儿子 else{ max1 = max(a[i][j],max(a[i-1][j*2],a[i-1][j*2-1]));//记录所构成子树的最大数值 if(a[i][j] < a[i-1][j*2] && a[i][j] < a[i-1][j*2-1]){ flag = 0; break; }else if(a[i][j] >= a[i-1][j*2]){ ans[id[i-1][j*2]] = a[i][j]; id[i][j] = id[i-1][j*2-1]; }else{ ans[id[i-1][j*2-1]] = a[i][j]; id[i][j] = id[i-1][j*2]; } a[i][j] = max1; } } } cin >> max1; if(a[k][1] <= max1) ans[id[k][1]] = max1; else flag = 0; if(flag == 0) cout<<"No Solution\n"; else{ for(int i = 1;i <= (1<<k);i++) cout<<ans[i]<<" \n"[i==(1<<k)]; } } int main() { IOS; // cin>>T; // while (T--) // run(); run(); return 0; }
L2-048 寻宝图
这里需要用vector来存,n*m <= 1e5,二维数组只能开到1e4。
本来想着数据可能很弱,打算直接用二维数组卡过去(/≧▽≦)/,结果被卡了一个点(24分)/(ㄒoㄒ)/~~。
回到这道题,就是一个连通块问题,写个dfs或者bfs就行了,所以这题关键是要想到用vector。
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; vector<int>f[N],st[N]; int cnt,sum; bool flag; int n,m; int dx[] = {-1,0,1,0},dy[] = {0,1,0,-1}; void dfs(int x,int y) { st[x][y] = true; if(f[x][y] > 1) flag = true; for(int i = 0;i < 4;i++) { int xx = x + dx[i],yy = y + dy[i]; if(xx >= 1 && xx <= n&&yy >= 1&&yy <= m&&f[xx][yy]&&!st[xx][yy]) { if(f[xx][yy] > 1) flag = true; dfs(xx,yy); } } } int main() { cin>>n>>m; for(int i = 1;i <= n;i++) { f[i].push_back(0); st[i].push_back(0); for(int j = 1;j <= m;j++) { char c; cin>>c; f[i].push_back(c-'0'); st[i].push_back(0); } } for(int i = 1;i <= n;i++) for(int j = 1;j <= m;j++) { if(f[i][j] && !st[i][j]) { flag = false; sum++; dfs(i,j); if(flag) cnt++; } } cout<<sum<<" "<<cnt; return 0; }
END✅
本文作者:Sunny不要停
本文链接:https://www.cnblogs.com/mrneojeep/p/17390383.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步