2025 SMU WINTER 4th
前言
内含蓝桥杯,天梯赛补题
蓝桥杯训练1
P8598错误票据
赛时对50分,赛后检查发现是因为我交的代码当出现"0 1 1 1 "这种样例时,断点的判断就不对(赛时交的代码是通过a[i]-1!=a[i-1]来判断的。这样在连续的数字的时候不行)
补题时用了set来去重
点击查看代码
void solve() {
ll n;cin>>n;
ll x;
ll duan=0,chong=0;
vector<ll>a;
set<ll>st;
ll minn=INT_MAX;
while(cin>>x)
{
a.push_back(x);
st.insert(x);
minn=min(minn,x);
}
sort(a.begin(),a.end());
for(ll i=1;i<(ll)a.size();++i)
{
if(a[i]==a[i-1])
{
chong=a[i];
break;
}
}
ll cnt=minn;
for(auto t:st)
{
if(t!=cnt)
{
duan=t-1;
break;
}
cnt++;
}
cout<<duan<<" "<<chong;
}
B4022蓝色的网易云
题意:给每首歌编一个播放顺序,使得相邻歌曲播放的题材不同
最开始我用了sort,但后面意识到,最后输出结果是要和输入的数据一比一对照的。
所以后面用vector开二维数组,记录编号
点击查看代码
void solve() {
ll n,m;cin>>n>>m;
vector<ll>c(n);
vector<vector<ll>> num(m+10); //记录编号
for(ll i=0;i<n;++i)
{
cin>>c[i];
num[c[i]].push_back(i+1);
}
vector<ll>ans;
while(ans.size()<n)
{
for(ll i=1;i<=m;++i)
{
if(!num[i].empty())
{
ans.push_back(num[i].back());
num[i].pop_back();
}
}
}
for(auto t:ans)
{
cout<<t<<'\n';
}
}
P8605网络寻路
图论忘得一干二净,,
详见代码
点击查看代码
void solve() {
ll n,m;
ll ans=0;
cin>>n>>m;
ll d[n+10]={0};
ll u[n+10]={0},v[n+10]={0};
for(ll i=0;i<m;++i)
{
cin>>u[i]>>v[i]; //各个节点
d[u[i]]++; //节点的入度
d[v[i]]++;
}
for(ll i=0;i<m;++i)
{
if(d[u[i]]>1&&d[v[i]]>1)
{
ans+=(d[u[i]]-1)*(d[v[i]]-1)*2; //计算该边作为中间边的个数*2
}
}
cout<<ans;
}
P8845小卡和质数
纯想暴力解去了,一点也没观察规律。
因为两个质数,只有为1和2时,才会异或成1
P8739重复字符串
题意:现有给定的一个字符串,最少需要多少次,可以时字符串变成一个k段且一样的字符串
贪心,我们先将原字符串分成k段(不能整除的就输出-1),判断每个段的每个位置出现频率最高的字母,再把每段每个位置的字母和频率最高的字母的不同给统计起来。
点击查看代码
void solve() {
ll k;cin>>k;
string s;cin>>s;
ll n=s.size();
ll ans=0;
s=" "+s;
if(n%k)
{
cout<<"-1\n";
return ;
}
ll temp=n/k;
for(ll i=1;i<=temp;++i)
{
ll a[30]={0};
ll tot=0;
for(ll j=i;j<=n;j+=temp)
{
a[s[j]-'a']++;
tot=max(tot,a[s[j]-'a']);
}
ans+=(k-tot);
}
cout<<ans<<'\n';
}
P10426宝石组合

(从洛谷上看来的题解)
由容斥原理我们可以将原式化简
s=j=gcd(ha,hb,hc);

(让人长脑子的思路啊)
赛时准备暴力解得三十分来着,但是代码里面直接用的是lcm〒▽〒,写得过程中还想着要么手写遍lcm,要么转换成__gcd(),但是给忘了。。导致编译失败,赛后才发现
反思:
1.想到要做补什么就去补,别给忘了
2.蓝桥杯这种赛时看不到结果的,多留心下编译是否成功(可能编译器版本不对)
点击查看代码
const ll N = 1e5 + 10;
const ll mod=1e9+7;
ll cnt[N];
ll h[N];
void solve() {
ll n;cin>>n;
for(ll i=1;i<=n;++i)
{
cin>>h[i];
}
for(ll i=1;i<=n;++i)
{
for(ll j=1;j*j<=h[i];++j)
{
if(h[i]%j==0)
{
cnt[j]++;
if(j*j!=h[i])
{
cnt[h[i]/j]++;
}
}
}
}
ll numgcd=0;
for(ll i=N-10;i>=1;--i)
{
if(cnt[i]>=3)
{
numgcd=i;
break;
}
}
sort(h+1,h+1+n);
ll tot=0;
for(ll i=1;i<=n;++i)
{
if(h[i]%numgcd==0)
{
cout<<h[i]<<" ";
tot++;
}
if(tot==3)
{
return ;
}
}
}
P10429拔河
题意:在给出的一串序列中找到将其分成两块的分界,使得两边差值最小
看题解有说用双指针做的
感觉自己双指针还是用的不够,学了之后还是得多写写(上个学期刚开始学感觉头大的stl和前缀和现在也觉得用的不错了)
e.p:下面代码中有三个while
第一个是同时扩展
当扩展到一个指针超过边界时,就会break第一个while
这时候就需要第二三个while继续来找到最小答案的情况
点击查看代码
const ll N = 1e3+ 10;
ll a[N];
ll ans=INT_MAX;
void solve() {
ll n;cin>>n;
for(ll i=1;i<=n;++i)
{
cin>>a[i];
}
for(ll i=1;i<=n;++i)
{
for(ll j=i+1;j<=n;++j)
{
ll l=i-1,r=j+1;
ll suml=a[i],sumr=a[j];
ans=min(ans,abs(suml-sumr));
while(l>=1&&r<=n)
{
if(suml>sumr) sumr+=a[r++];
else suml+=a[l--];
ans=min(ans,abs(suml-sumr));
}
while(l>=1)
{
suml+=a[l--];
ans=min(ans,abs(suml-sumr));
}
while(r<=n)
{
sumr+=a[r++];
ans=min(ans,abs(suml-sumr));
}
}
}
cout<<ans<<'\n';
}
反思
第一次蓝桥杯训练,说实话感觉感觉训练得并不是很好,感觉有些题做起来有点生疏(思路卡卡的),对我来说不是很好上手〒▽〒
还是得多练习搜索的〒▽〒
天梯训1
L1-6 剪切粘贴
题意:要编一个程序实现剪切粘贴的功能(剪切和粘贴的位置都会给出)
我最开始没注意到要粘贴的位置都是连在一起的,就导致总是达不到样例
解决要粘贴的位置是连在一起的也简单:直接先定义一个字符串将其连在一起,在原字符串中查找这个字符串
点击查看代码
void solve() {
string s;cin>>s;
s=" "+s;
ll n;cin>>n;
while(n--)
{
ll a,b;cin>>a>>b;
string s0=s.substr(a,b-a+1); //用substr函数
s.erase(a,b-a+1); //erase函数
string c,d;cin>>c>>d;
string s1=c+d; //合在一起去查找
auto poss0=s.find(s1);
if(poss0==string::npos)
{
s+=s0;
}else{
s.insert(poss0+c.size(),s0);
}
}
s.erase(s.begin());
cout<<s<<'\n';
}
L1-7 分寝室
这道题交第一发卡了两个测试点没过,后面觉着应该是题目条件没满足
1.不允许单人睡一间寝室(我还是特判了下)
for(ll i=1;i<=n&&i<n0&&(n-i)<n1;++i)
注意:这题我是使用x+y=1使得y=x-1和x,所以在循环的过程中要注意循环条件的满足
L2-1 堆宝塔

样例,答案是4 5
11
10 8 9 5 12 11 4 3 1 9 15
思路:按照题目描述模拟即可,但是要注意最开始是如果a为空或者要插入的元素比a数组里最后的元素小才插入a数组(第一次写就是没判a为空,导致数据一直进不去)
最后也要注意判,如果a数组还有cnt++,b数组同理
L2-2 天梯赛的赛时安排
这个困住我的是想不明白怎么去处理分够c之后剩下的人,看了别人写的之后,发现用优先队列写的,就很好处理了剩下的人的问题。(用优先队列而不是队列,我觉得是贪心思想的体现(先把剩的人多的队伍排好(题目有要求同一队尽可能同一考场))
思路:一行一行读入字符串和数组,然后直接计算输出,留下res待后续算剩下的人要多少房间。循环,当队列非空的时候,取顶部元素(即优先队列里面的最大值),for循环ans数组(也就是每个队伍剩的人),如果该元素小于等于c减去ans[i],那么就纳入ans[i](感觉这个地方的处理也很巧妙,直接纳入)。如果循环下来还是没有的话,就单开一间
点击查看代码
void solve() {
ll n,c;cin>>n>>c;
ll res=0;
priority_queue<ll>q;
for(ll i=1;i<=n;++i)
{
string s;cin>>s;
ll x;cin>>x;
cout<<s<<" "<<(x+c-1)/c<<endl; //(x+c-1)能防止类似于c为30时,数据为28的情况
res+=x/c;
if(x%c)
{
q.push(x%c);
}
}
vector<ll>ans;
while(!q.empty())
{
ll temp=q.top();
q.pop();
bool f=false;
for(ll i=0;i<(ll)ans.size();++i)
{
if(temp<=c-ans[i])
{
f=true;
ans[i]+=temp;
break;
}
}
if(!f)
{
ans.push_back(temp);
res++;
}
}
cout<<res<<endl;
}
L2-4 寻宝图

样例,答案是 7 2
10 11
01000000151
11000000111
00110000811
00110100010
00000000000
00000111000
00114111000
00110010000
00019000010
00120000001
用的bfs做
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const ll N = 1e5 + 10;
ll dx[]={-1,1,0,0};
ll dy[]={0,0,-1,1};
vector<string>g;
map<pair<ll,ll>,bool>vis;
ll n,m;
bool check(ll a,ll b)
{
if((a>=0&&a<n)&&(b>=0&&b<m)&&(g[a][b]-'0')&&(!vis[{a,b}]))
{
return true;
}
return false;
}
ll bfs(ll a,ll b)
{
queue<pair<ll,ll>>q;
q.push({a,b});
vis[{a,b}]=true;
bool have=false;
while(q.size())
{
ll x=q.front().first;
ll y=q.front().second;
q.pop();
if(g[x][y]>='2'&&g[x][y]<='9')
{
have=true;
}
for(ll k=0;k<4;++k)
{
ll u=x+dx[k];
ll v=y+dy[k];
if(check(u,v))
{
// cout<<u<<" "<<v;
vis[{u,v}]=true;
q.push({u,v});
}
}
}
if(have) return 1;
else return 0;
}
void solve()
{
cin>>n>>m;
getchar();
for(ll i=0;i<n;++i)
{
string s;
getline(cin,s);
g.push_back(s);
}
ll cnt=0,val=0;
for(ll i=0;i<n;++i)
{
for(ll j=0;j<m;++j)
{
if(g[i][j]=='0'||vis[{i,j}])
{
continue;
}
val+=bfs(i,j);
cnt++;
// cout<<i<<" "<<j<<'\n';
}
}
cout<<cnt<<" "<<val;
}
int main()
{
// ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int t=1;
// cin>>t;
while(t--)
{
solve();
}
return 0;
}
这段代码我贴的完整代码,是因为我卡了一下午,而罪魁祸首是我同时用了关闭流同步和getchar()


蓝桥杯训练2
P8692 数正方形

点击查看代码
const ll mod=1e9+7;
void solve() {
ll n;cin>>n;
n-=1;
ll ans=0;
for(ll i=1;i<=n;++i)
{
ll temp=(n-i+1);
ans=(ans+(temp*temp*i))%mod;
}
cout<<ans<<'\n';
}
学到了这种思考方式,之前碰到这种题老是会想概率(组合)啥的)
总结
这周是寒假训练最后一周了,状态比上周好。但是还是有点不适应蓝桥杯赛制啊啊啊,做题总有思考不到的地方。
温故了bfs算法,之前都是用在类似于寻宝图这种题上,其他类型的题目接下来几天得趁热练练手。

浙公网安备 33010602011771号