文章目录
The Second Week
路漫漫其修远兮,吾将上下而求索 ————屈原
一、前言
周一打了场cf,晚上实在太困了打得很不好,也没打完,花点时间补题吧。周四整忘了直接开训练了,下次再来。
周二打了天梯模拟,反正二十分题及以下题全都做出来了,只做出了一题二十五分题,一个大二的都没打过呢。一些STL根本用不出来,纯暴力手写了。
周六成信大天梯赛,前七题八十分我简直无言以对,做题速度太慢,一直在修改,后来也没有时间看别的题目。当然也不会做。
周二天梯模拟,周六试了一下电子科大的校赛,微笑点头.jpg。这比赛都不知道有没有补题的必要了。
二、算法
1.STL
这几道题没什么难度,不用STL也能写出来,主要是熟悉一下stack,queue,vector之类的。不然总是用数组int,有点低级。当然主要是因为我比赛时一直没能过全部案例太可气了。
<1>(SMU 2024 spring 天梯赛1 7—8)
机工士姆斯塔迪奥 分数20
题解:
题意表达为输入构造一个n行m列的地图,q组数字t,c,t=1表示选择c行消失,t=0表示选择c列消失,计算最后留下来的格子。
本题考虑删除相同俩行的情况,采用set自动去重功能,注意set的插入和便利。运用数学思维先删除ls行个格子,再删去hs列格子即可。
代码:
#include<iostream>
#include<set>
using namespace std;
int main(){
int n,m,q;
cin>>n>>m>>q;
set<int>h;
set<int>l;
for(int i=0;i<q;i++){
int t,c;
cin>>t>>c;
if(t==1){
l.insert(c); //set的插入
}
if(t==0){
h.insert(c);
}
}
int sum=n*m;
int ls=0,hs=0;
for(auto i:l){ //set的遍历
ls++; //计算l中元素数量
}
for(auto i:h){ //同上
hs++;
}
sum-=(ls*n);
sum-=(hs*(m-ls));
cout<<sum<<endl;
}
<2>(SMU 2024 spring 天梯赛1 7—9)
彩虹瓶 分数25
题解:
题意为输入彩虹瓶数量n,容量m,k组判断样例,每组n个数字,要求按字母序取瓶子,如果存放的瓶子超过容量判断st为false,或者要取出非栈顶的元素也判定为false,然后按照st的状态输出即可。注释了一些导致我未ac的原因。
代码:
#include<iostream>
#include<stack>
using namespace std;
int n,k;
size_t m;
stack<int>box;
void solve(){
int id=1;
bool st=true;
while(!box.empty()){
box.pop();
} //清空栈
for(int i=1;i<=n;i++){
int ls;
cin>>ls;
box.push(ls);
if(!box.empty()&&box.top()==id){
//为什么要在这先判断一次呢,相当于如果现在手上的货物不用放在货架上
//所以它的数量不会影响box.size()
box.pop();
id++;
}
if(box.size()>m){ //超过货架的容量
st=false;
}
while(!box.empty()&&box.top()==id){ //我的天这里因为循环条件的先后导致段错误
box.pop(); //先判断栈是否为空
id++; //尝试访问栈顶元素导致未定义行为就是段错误
}
}
if(id!=n+1){ //因为最后拿出编号为n的货物后id还会加一
st=false;
}
if(st){
cout<<"YES"<<endl;
}
else cout<<"NO"<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin>>n>>m>>k;
while(k--){
solve();
}
return 0;
}
<3>(洛谷P2058)
周二天梯赛的一道题,当时拿了四十分,暴力解法。本来看懂代码之后想自己再写一遍的,但是一直过不了,改着改着就改成跟学长的代码一模一样了…加了点自己的注释理解,下周有时间再做一次。
题解:
题意较为繁琐,n行数据分别输入到达海港的时间t和船上的乘客数量k,k个整数表示船上乘客的国籍,试求出86400秒内所有乘船到达的乘客来自多少个不同的国家。
mp用于记录国籍与人数,所以只需输出mp.size()就可以知道国家数,q升序排列时间与国家,时间用于确认二十四小时以内,国家数等于0的时候清除此mp,每次运作都要弹出q。
代码:
#include <iostream>
#include <map>
#include <queue>
using namespace std;
#define PII pair<int,int>
map<int,int>mp;
priority_queue<PII,vector<PII>,greater<PII>>q; //以q.first后second的升序队列
int main() {
int n;
std::cin>>n;
while(n--){
long long t,k;
cin>>t>>k;
while(!q.empty()&&t-86400>=q.top().first){ //从最小的开始,不符合条件的弹出
mp[q.top().second]--;
if(mp[q.top().second]==0){
mp.erase(q.top().second); //清除这个mp为后面计算size作准备
}
q.pop();
}
for(int i=1;i<=k;i++){
int x;
cin>>x;
mp[x]++; //mp用于计算国籍与人数
q.push({t,x}); //输入
}
cout<<mp.size()<<endl;
}
return 0;
}
2.高精度运算法
<1>(CF Gym104678F)
其实已经是寒假的一道题了,做天梯练习题的时候做到了一题高精度算法,没做出来,这可能就是没补题的后果,要是补题了可能就做出来了,还是先上网学习了之后再写的,过了这题先。
题解:
题意非常简单,给出俩个小于十的十的十五次方的数字,求和。
由于数据范围已经超过long long了,也没有比的更大的int类型,所以得采用string字符串的方式,逐位相加并输出,注意要是最大一位超过十要进一即可。
代码:
#include<iostream>
#include<vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
string a, b;
cin >> a >> b;
vector<int> A, B;
for (int i = a.size() - 1; i >= 0; i--)A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--)B.push_back(b[i] - '0');
int t = 0;
vector<int> c;
for (int i = 0; i < a.size() || i < b.size(); i++) {
if (i < a.size())t += A[i];
if (i < b.size())t += B[i];
c.push_back(t % 10);
t /= 10;
}
if (t)c.push_back(1);
for (int i = c.size() - 1; i >= 0; i--) {
cout << c[i];
}
return 0;
}
<2>(SMU 2024 spring 天梯训练1 7—7)
整除光棍 分数20
题解:
给出一个不以5结尾的正奇数x,求s使二者相乘的数字全部由1组成,输出s以及有几个1数n。
直接暴力对t(只包含1的光棍数会超时),但是ioi赛制,15分,考虑对其余数进行相应操作,代码写得有点问题可优化。大致思路如下,可将几个if判断合并,count计算的是位数n。
代码:
#include<iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int x;
cin>>x;
long long int t=1;
int ans=1;
while(t%x!=0){
t=t*10+1;
ans++;
}
cout<<t/x<<' '<<ans;
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int x;
cin >> x;
int count;
long long int n;
int s[1000000];
if (x == 1) {
cout << 1 << ' ' << 1 << endl;
} else if (x == 3) {
cout << 37 << ' ' << 3 << endl;
} else if (x == 7) {
cout << 15873 << ' ' << 6 << endl;
} else if (x == 9) {
cout << 12345679 << ' ' << 9 << endl;
} else if (x == 11) {
cout << 1 << ' ' << 2 << endl;
}
if (11 < x && x <= 110) {
n = 111;
int j = 0;
s[j] = n / x;
n = n % x;
count = 3;
while (n != 0) {
j++;
n = n * 10 + 1;
s[j] = n / x;
n = n % x;
count++;
}
for (int i = 0; i <= count - 3; i++) {
cout << s[i];
}
cout << ' ' << count << endl;
}
if (x == 111) {
cout << 1 << ' ' << 3 << endl;
}
if (111 < x && x <= 999) {
n = 1111;
int j = 0;
s[j] = n / x;
n = n % x;
count = 4;
while (n != 0) {
j++;
n = n * 10 + 1;
s[j] = n / x;
n = n % x;
count++;
}
for (int i = 0; i <= count - 4; i++) {
cout << s[i];
}
cout << ' ' << count << endl;
}
return 0;
}
3.其它
<1>(洛谷P5657)
一道我们天梯训练赛的25分题在luogu里竟然是签到题…我当时一点思路也没有结果就这么几行代码。
#include<iostream>
using namespace std;
int n;
unsigned long long k;
int main(){
std::cin>>n>>k;
k^=k>>1; //k跟k右移一位的数字异或的结果赋值给k
while(n--)
std::cout<<(k>>n&1); //循环n次输出此数即可
//每次输出k右移n位后的数字与1按位与后的第一位数字
}
三、总结
Clang-format的使用是ctrl+alt+l,注意格式化代码,以后争取手写。
感知了一下我的水准,20分以下还是能拿下的,20分可能会有不会做的(但是能拿不少分),25分可能会有会做的,30绝对不会做。感知我的水准还是比较精准的,但是平时的练习题会比比赛题简单很多,最好能争取平时练习题二十五分及以下全都做出来。我在说什么我一点也写不出来25分题我在梦游吧…算了一下20分及以下总共一百分,俩道二十五分题就可以拿一百五,加油。
就这样吧,做了点天梯练习题的低分题,一直卡真服了。