2025河北秦皇岛CCPC【部分题解】
文章目录
- 我讨厌模拟题
- H.What isallyouneed?
- J.Generate01String
- M - 第九届河北省大学生程序设计竞赛
我讨厌模拟题
题目来源:ProblemK.UNO !
解题思路
这个题一开始就是纯模拟,用的数组以及动态数组做下标方便删除为0的情况,虽然很麻烦,但也是真的麻烦,但这道题用双端队列写更容易些,一开始让他们顺序入队,从队头开始遍历,首先判断出了这张牌后剩余的牌数是非为0,若为0直接踢出,否则进行相应的操作后,再将其踢出队头,并加入队尾,注意如果遇到反转,从队尾开始遍历,方法相同,只是将队头变队尾,从队尾删除放队头等。所有操作完成后按顺序输出即可。
代码实现
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define fi first
#define se second
#define pf push_front
#define pb push_back
const int N=2e5+5;
int n,m,a[N],b[N];signed main()
{IOS; cin>>n>>m;deque<PII>q;for(int i=1;i<=n;i++){cin>>a[i];q.pb({a[i],i});}string s;cin>>s; int x,y;int f=1;//做标记方向,1为顺时针,0为逆时针 for(int i=0;i<s.size();i++){if(f)//当前为正向{if(s[i]=='C')//普通牌{if(q.front().fi==1)q.pop_front();//如果只剩一张牌,出完这张牌后就直接出队了else//否则排到后面,并且牌数-1 {x=q.front().fi-1;y=q.front().se;q.pop_front();q.pb({x,y}); } } else if(s[i]=='S')//禁止牌{if(q.front().fi==1)q.pop_front();else{x=q.front().fi-1;y=q.front().se;q.pop_front();q.pb({x,y}); }//对禁止的效果进行操作,下一个玩家禁止出牌,即直接跳过,出队并排在队尾x=q.front().fi;y=q.front().se;q.pop_front();q.pb({x,y}); }else if(s[i]=='R')//反转牌,将顺序反转{f=0;//标记方向变换if(q.front().fi==1)q.pop_front(); //同样需要判断else{q.front().fi--;//这时不需要再排在后面了,因为顺序已经反转了,顺序的队首相当于逆序的队尾 } }else//加罚两张牌并禁止出牌{if(q.front().fi==1)q.pop_front();else{x=q.front().fi-1;y=q.front().se;q.pop_front();q.pb({x,y}); }x=q.front().fi+2;//下家加罚两张牌 y=q.front().se;q.pop_front();q.pb({x,y}); } }else//f=0,逆序,和顺序的思路一样,只是把队头和队尾调换一下即可,从队尾出队,排在队头{if(s[i]=='C'){if(q.back().fi==1)q.pop_back();else{x=q.back().fi-1;y=q.back().se;q.pop_back();q.pf({x,y});}}else if(s[i]=='S'){if(q.back().fi==1)q.pop_back();else{x=q.back().fi-1;y=q.back().se;q.pop_back();q.pf({x,y});}x=q.back().fi;y=q.back().se;q.pop_back();q.pf({x,y});}else if(s[i]=='R'){f=1;if(q.back().fi==1)q.pop_back();else{q.back().fi--;}}else{if(q.back().fi==1)q.pop_back();else{x=q.back().fi-1;y=q.back().se;q.pop_back();q.pf({x,y});}x=q.back().fi+2;y=q.back().se;q.pop_back();q.pf({x,y});} } }while(q.size()){if(q.front().fi>=0)b[q.front().se]=q.front().fi;q.pop_front();}for(int i=1;i<=n;i++)cout<<b[i]<<endl;return 0;}
H.What isallyouneed?
题目来源: ProblemH.What isallyouneed?
解题思路
很简单的一道题目,从后往前找“isallyouneed”,如果能找到输出前面的部分,否则输出-1,巧妙利用rfind函数和substr函数
代码实现
#include<bits/stdc++.h>
using namespace std;
int main()
{string s,s1;cin>>s;s1="isallyouneed";int pos=s.rfind(s1);if(pos==-1)//如果没找到cout<<"No"<<endl;else{cout<<"Yes"<<endl;for(int i=0;i<pos;i++)cout<<s[i];}return 0;}
J.Generate01String
题目来源: ProblemJ.Generate01String
解题思路
不管用那种方法,最后得到的01串0和1的个数一定相同,并且总数一定是偶数,接着,我们可以把这个01串分成一些01或10串,这样将复杂的问题分解成小问题,用两个变量分别记录多余的0和1的个数,如果为0是就可以转变位置变量,最后输出即可。
代码实现
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
#define fi first
#define se second
#define int long long
const int N=205;
string s;
signed main()
{cin>>s;int x=count(s.begin(),s.end(),'0');//0的个数int y=count(s.begin(),s.end(),'1');//1的个数if((x+y)%2!=0||x!=y){cout<<-1<<endl;return 0;} x=0,y=0;int t=1;vector<PII>v;for(int i=0;i<s.size();i++){if(s[i]=='1'){if(y==0){v.push_back({t,2});x++;}else{y--;t++;}}else{if(x==0){v.push_back({t,1});y++;}else{x--;t++;}}} cout<<v.size()<<endl;for(auto i :v)cout<<i.fi<<" "<<i.se<<endl;return 0;
}
M - 第九届河北省大学生程序设计竞赛
题目来源:M - 第九届河北省大学生程序设计竞赛
解题思路
这道题可以用搜索也可以用二进制来做,这里建议大家了解一下bitset函数。
代码实现
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int N=205;
int n,m,a,b,c,x,y,z;
string s;
void solve()
{cin>>n>>m;for(int i=1;i<=m;i++)cin>>s[i];cin>>a>>b>>c>>x>>y>>z;for(int i=1;i<=(1<<n)-1;i++){bitset<20>bt(i);if(bt.count()>=10&&bt.count()<=13){vector<int>v;v.push_back((int)2e18);for(int j=1;j<=m;j++){bitset<20>c(s[j]);c&=bt;v.push_back(c.count());}sort(v.begin(),v.end(),greater<int>());if(v[a]==x&&v[b]==y&&v[c]==z){cout<<bt.count()<<endl;for(int j=n-1;j>=0;j--)if(bt[j])cout<<n-j<<" ";return ;}}}cout<<-1<<endl;
}
signed main()
{IOS;int _=1;cin>>_;while(_--)solve(); return 0;
}