由于去年参加过比赛,这几天又做了一下vp,相比去年进步了一些。整体来说感觉难度不大,除了最后一题,整体来说拿到250+的分数还是有机会的。
L1总计八道题,100分会语法即可拿满分,完全是手速。
L1-1 人与神 (5 分)
直接输出即可
#include<bits/stdc++.h>
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout<<"To iterate is human, to recurse divine.";
return 0;
}
L1-2 两小时学完C语言 (5 分)
按照题意模拟即可
#include<bits/stdc++.h>
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int x,y,z;
cin>>x>>y>>z;
cout<<x-y*z;
return 0;
}
L1-3 强迫症 (10 分)
接收一个四位数或者试六位数按照题意转换一下格式即可
#include<bits/stdc++.h>
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
string str;
cin>>str;
int x=(str[0]-'0')*10+(str[1]-'0');
if(str.size()==4)
{if(x<22){
if(x>=10)cout<<"20"<<x<<"-"<<str[2]<<str[3];
else cout<<"200"<<x<<"-"<<str[2]<<str[3];
} else {
cout<<"19"<<x<<"-"<<str[2]<<str[3];
}
} else {
cout<<str[0]<<str[1]<<str[2]<<str[3]<<"-"<<str[4]<<str[5];
}
return 0;
}
L1-4 降价提醒机器人 (10 分)
注意一个是整数一个是实数
#include<bits/stdc++.h>
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int x,w;
cin>>x>>w;
vector<double>sd;
for(int i=0;i<x;i++){
double k;
cin>>k;
if(k<w)sd.push_back(k);
}
for(int i=0;i<sd.size();i++){
auto k=sd[i];
printf("On Sale! %.1lf\n",k);
}
return 0;
}
L1-5 大笨钟的心情 (15 分)
按题意输出即可
#include<bits/stdc++.h>
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
vector<int>a(24);
for(int i=0;i<24;i++)cin>>a[i];
int x;
while(cin>>x){
if(x>23||x<0)break;
cout<<a[x];
if(a[x]>50)cout<<" Yes\n";
else cout<<" No\n";
}
return 0;
}
L1-6 吉老师的回归 (15 分)
这里建议大家了解一下getline这个函数
#include<bits/stdc++.h>
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
cin>>n>>m;
vector<int>res;
vector<string>sd;
// getchar();
string tt;
getline(cin,tt);
for(int i=0;i<n;i++){
string str;
getline(cin,str);
if(str.find("easy")==string::npos&&str.find("qiandao")==string::npos){
res.push_back(i);
}
sd.push_back(str);
}
// cout<<res.size()<<"--";
if(m>=res.size()){
cout<<"Wo AK le";
} else {
cout<<sd[res[m]]<<"\n";
}
return 0;
}
L1-7 天梯赛的善良 (20 分)
最大数和最少数的个数如果不会STL的话直接遍历一次记录也可以考验手速
#include<bits/stdc++.h>
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
map<int,int>mp;
for(int i=0; i<n; i++){
int x;
cin>>x;
mp[x]++;
}
auto k1=mp.begin();
auto k2=prev(mp.end());
cout<<k1->first<<" "<<k1->second<<endl;
cout<<k2->first<<" "<<k2->second<<endl;
return 0;
}
L1-8 乘法口诀数列 (20 分)
用数组或者vector模拟这个过程就可以了,以为一位数乘以一位数最多会是两位数,判断只需要判断结果大于十还是小于十即可
#include<bits/stdc++.h>
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,t;
cin>>n>>m>>t;
vector<int>a;
a.push_back(n);
a.push_back(m);
int pos=0;
while(1){
int k=a[pos]*a[pos+1];
if(k<10)a.push_back(k);
else {
a.push_back(k/10);
a.push_back(k%10);
}
pos++;
if(a.size()>=t){
break;
}
}
for(int i=0;i<t;i++){
cout<<a[i];
if(i!=t-1)cout<<" ";
}
return 0;
}
L2稍微有点难度,如果会用set map vector stack可以很快做完留给做L3的时间
L2-1 包装机 (25 分)
按照题意相当于模拟一个不断入栈出栈的过程,了解一个stack可以很容易解决,注意可能会出现的运行错误,空栈时出栈
#include<bits/stdc++.h>
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,k;
cin>>n>>m>>k;
vector<int>a(n);
vector<string>b(n);
for(int i=0;i<n;i++){
cin>>b[i];
}
int t;
// vector<char>res;
string res;
stack<char>s;
while(cin>>t){
if(t==-1)break;
if(a[t]>=m)continue;
if(t==0){
if(!s.empty()){
res+=s.top();
s.pop();
}
} else {
if(s.size()>=k){
res+=s.top();
s.pop();
}
s.push(b[t-1][a[t]]);
a[t]++;
}
}
cout<<res;
return 0;
}
L2-2 病毒溯源 (25 分)
104 的数据量,题目上给出最开始的溯源只有一个,且不存在循环变异,先确定溯源,dfs一次找到最长链是多少在dfs一次把最长链且序号最小的一个输出即可,找最长链是一个典型的dfs加回溯,回溯的时候记录最长的子链并更新,第二次dfs的时候需要排序,排序的大小按照首先链最长其次序号最小即可,当然也可以遍历一遍。
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
vector<int>a[N];
int in[N];
int dep[N];
void dfs(int s){
if(a[s].size()==0){
dep[s]=1;
}
for(auto k:a[s]){
dfs(k);
dep[s]=max(dep[s],dep[k]+1);
}
}
vector<int>res;
void dfs2(int x){
sort(a[x].begin(),a[x].end(),[&](int x,int y){
if(dep[x]!=dep[y]){
return dep[x]>dep[y];
} else {
return x<y;
}
});
res.push_back(x);
if(a[x].size())dfs2(a[x][0]);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,t,x;
cin>>n;
for(int i=0;i<n;i++){
cin>>t;
for(int j=0;j<t;j++){
cin>>x;
a[i].push_back(x);
in[x]++;
}
}
int s;
for(int i=0;i<n;i++){
if(!in[i]){
s=i;
break;
}
}
dfs(s);
dfs2(s);
cout<<res.size()<<"\n";
for(int i=0;i<res.size();i++){
cout<<res[i];
if(i!=(int)res.size()-1)cout<<" ";
}
return 0;
}
L2-3 清点代码库 (25 分)
把相同的东西放在一起,记录出现的次数,然后把出现次数多的序号小的放在一起,可以用set套vector,然后在写一个结构题重载一下运算符即可
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct sk{
int x;
vector<int>sd;
friend bool operator< (const sk& a,const sk &b){
if(a.x!=b.x)return a.x>b.x;
for(int i=0;i<m;i++){
if(a.sd[i]!=b.sd[i])return a.sd[i]<b.sd[i];
}
};
};
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
map<vector<int>,int>mp;
cin>>n>>m;
for(int i=0;i<n;i++){
vector<int>a(m);
for(int j=0;j<m;j++){
cin>>a[j];
}
mp[a]++;
}
vector<sk>res;
for(auto k:mp){
res.push_back({k.second,k.first});
}
sort(res.begin(),res.end());
cout<<res.size()<<"\n";
for(int i=0;i<res.size();i++){
cout<<res[i].x<<" ";
for(int j=0;j<m;j++){
cout<<res[i].sd[j];
if(j!=m-1)cout<<" ";
}
cout<<"\n";
}
return 0;
}
L2-4 哲哲打游戏 (25 分)
直接按题意模拟即可
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
vector<int>a[N];
int k[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
int t;
cin>>t;
a[i].resize(t);
for(int j=0;j<t;j++){
cin>>a[i][j];
}
}
int now=1;
k[1]=now;
for(int i=1;i<=m;i++){
int opt;
cin>>opt;
int w;
if(opt==0){
cin>>w;
now=a[now][w-1];
} else if(opt==1){
cin>>w;
k[w]=now;
cout<<now<<"\n";
} else {
cin>>w;
now=k[w];
}
}
cout<<now<<"\n";
return 0;
}
L3-1 森森旅游 (30 分)
交了好多发都是29分。。。如果ACM赛制可能会卡很久 一个经典的图论题,中间多加了一个RMQ的算法相当于两个算法的小综合,首先经过某点的时候可以把钱全部兑换成旅游金,是全部,所以很容易想到从源点建到n的正相边,边权现金,从n到源点的反向边边权旅游金,然后枚举1到n为中转点,因为政策的改变会发生更改所以要记录一下,可以用一个线段树记录然后单点更改,应该也可以用multiset,不断的删除插入。然后这样可以得29分,因为题目保证的是从1可以到n,但是没有保证从1可以到n-1,所以有些城市可能到不了特判一下就可以三十分了,然后单源最短路的dijstra可以自行学习一下,rmq不会的也可以自行学习一下。
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
#define ll long long
#define int ll
vector<tuple<int,int>>e[N],r[N];
int dis[N],rt[N];
int sd[N];
bool v[N],f[N];
struct Sgt{
int w;
}sgt[N<<2];
#define lson (k<<1)
#define rson (k<<1|1)
void pushup(int k){
sgt[k].w=min(sgt[lson].w,sgt[rson].w);
}
#define mid (l+r>>1)
ll rk[N];
void build(int l,int r,int k=1){
if(l==r){
sgt[k].w=rk[l];
return;
}
build(l,mid,lson);
build(mid+1,r,rson);
pushup(k);
}
void update(int l,int r,int pos,int k=1){
if(l==r){
sgt[k].w=rk[l];
return;
}
if(pos>mid){
update(mid+1,r,pos,rson);
} else {
update(l,mid,pos,lson);
}
pushup(k);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,q;
cin>>n>>m>>q;
for(int i=0;i<m;i++){
int u,v,w1,w2;
cin>>u>>v>>w1>>w2;
e[u].push_back({v,w1});
r[v].push_back({u,w2});
}
for(int i=1;i<=n;i++){
cin>>sd[i];
}
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q1,q2;
q1.push({0,1});
q2.push({0,n});
for(int i=0;i<=n;i++)dis[i]=rt[i]=1e18;
dis[1]=0;
rt[n]=0;
while(q1.size()){
auto [w,u]=q1.top();
q1.pop();
if(v[u])continue;
v[u]=1;
for(auto [v,t]:e[u]){
if(dis[v]>dis[u]+t){
dis[v]=dis[u]+t;
q1.push({w+t,v});
}
}
}
while(q2.size()){
auto [w,u]=q2.top();
q2.pop();
if(f[u])continue;
f[u]=1;
for(auto [v,t]:r[u]){
if(rt[v]>rt[u]+t){
rt[v]=rt[u]+t;
q2.push({w+t,v});
}
}
}
//保证可以到n但是不保证可以到i
for(int i=1;i<=n;i++){
int w=(rt[i]+sd[i]-1)/sd[i]+dis[i];
if(rt[i]>=1e18||dis[i]>=1e18){
rk[i]=1e18;
} else
rk[i]=w;
}
build(1,n,1);
while(q--){
int x,w;
cin>>x>>w;
ll ss=(rt[x]+w-1)/w+dis[x];
// rk[x]=ss;
if(rk[x]!=1e18){
rk[x]=ss;
}
update(1,n,x,1);
cout<<sgt[1].w<<"\n";
}
return 0;
}
L3-2 还原文件 (30 分)
暴力搜索了一下三十分,有点无语。。。第一时间想到的是hash数组,然后暴力搜一下,只是先写了个暴力试试就满分了,不太清楚复杂度怎么证明只是单纯的感觉数据很难构造
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int dp[N];
int a[N];
vector<int>e[111];
bool vis[111];
int m,n;
void dfs(int x){
if(x==n){
int now=1;
vector<int>res;
while(now!=n){
res.push_back(dp[now]);
now=e[dp[now]].size()-1+now;
}
for(int i=0;i<res.size();i++){
cout<<res[i];
if(i!=res.size()-1)cout<<" ";
}
exit(0);
}
for(int i=1;i<=m;i++){
bool ok=1;
if(vis[i])continue;
for(int j=0;j<e[i].size();j++){
if(a[x+j]!=e[i][j]){
ok=0;
break;
}
}
if(ok){
vis[i]=1;
dp[x]=i;
// cout<<i<<"--";
dfs(x+e[i].size()-1);
vis[i]=0;
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
cin>>m;
for(int j=1;j<=m;j++){
int t;
cin>>t;
e[j].resize(t);
for(int r=0;r<t;r++){
cin>>e[j][r];
}
}
dfs(1);
// cout<<0<<"l";
return 0;
}
L3-030 可怜的简单题 (30 分)
只有一个答案的题目为出题组好评,这样大家就不用罚坐了而是在这里试最后一题的答案qwq,我那时候试的时候1,2,…100… 现在的话可能会试1/2,1/3…1/n…还是有进步的