Atcoder Beginner Contest 167
赛场实况:
训练反思: A题签到不说了,B题第一眼没看清楚数据范围,写了一堆然后仔细一看1e12果断不能暴力..立马换了一个写法,连交2发wa(细节啊细节!!),C题看了半天英语没看懂说了什么,拿翻译软件翻了一下才算是懂,小数据范围一眼看出dfs,然后一发过(英语好菜qaq),D也是个简单题,就是找循环节,但是一直RE(想了半小时没想懂为什么),最后仔细看了一下题发现可以自己指向自己.....那么一开始就是死循环1的情况,压哨AC...。EF等我有空了补一下再更新。
A:Registration
签到题没意思,不说了。
#include<bits/stdc++.h> #define ll long long #define endl '\n' #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; int main(){ string s,t;cin>>s>>t; if(t.length()==s.length()+1){ int flag=0; for(int i=0;i<s.length();i++){ if(s[i]!=t[i]){ flag=1;break; } } if(flag) puts("No"); else puts("Yes"); }else{ puts("No"); } }
B:Easy Linear Programming
签到题,依次贪心a,然后再贪心b,最后贪心c,注意数据范围,别无脑莽(比如我)
#include<bits/stdc++.h> #define ll long long #define endl '\n' using namespace std; int main(){ ll a,b,c,k;cin>>a>>b>>c>>k; ll ans=0; if(k<=a){ ans=k;cout<<ans<<endl;return 0; } else if(k>a&&k<=a+b){ ans+=a; cout<<ans<<endl;return 0; }else if(k>(b+a)){ ans+=a; ans-=(k-(a+b)); cout<<ans<<endl;return 0; } }
C:Skill Up
题意:n行,m列,然后每一行购买的代价是C[i],如果你购买了该i行,你m个技能每个技能经验+a[i][j],然后题目要求每个技能的经验严格>=x,问你最小购买的代价.
我不知道有什么简便做法,反正我看到n,m<=12就觉得是dfs,但是我看榜单过的速度好快...或许有更简单的做法吧。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int a[20][20],c[20],cur[20];int n,m,k,ans=INF; void dfs(int x,int sum){ for(int i=1;i<=m;i++){ cur[i]+=a[x][i]; } int fg=1; for(int i=1;i<=m;i++){ if(cur[i]<k) fg=0; } if(fg==1) {ans=min(ans,sum+c[x]);} for(int i=x+1;i<=n;i++){ dfs(i,sum+c[x]); for(int j=1;j<=m;j++){ cur[j]-=a[i][j]; } } } int main(){ cin>>n>>m>>k; for(int i=1;i<=n;i++){ cin>>c[i]; for(int j=1;j<=m;j++){ cin>>a[i][j]; } } for(int i=1;i<=n;i++){ mem(cur,0); dfs(i,0); } if(ans!=INF) cout<<ans<<endl; else cout<<-1<<endl; }
D:Teleporter
题意:有N个点,每个点与to[i]有个单向边,问从1开始走(1是第0个点),第k个点是什么。
解法:就是找循环节,然后如果k在循环节开始之前,那无所谓直接硬钢,如果在循环节之内了,那你需要减去循环节之前的数目,然后对于循环节总数取模确定你在循环节里的哪个位置。坑点,一个点可以自己走向自己(我没注意那么多一开始,以为题目默认不能这样...否则你会有3个RE点,我调了半小时心态都崩了,菜是原罪)
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=4e6+5; ll to[maxn],pos[maxn],vis[maxn],mp[maxn]; int main(){ ll n,k;cin>>n>>k; for(int i=1;i<=n;i++){ cin>>to[i]; } pos[1]=1;vis[1]=1;mp[1]=1; ll now=to[1],cnt=1,dis=0,l=0; while(!vis[now]){ vis[now]=++cnt; mp[cnt]=now; now=to[now]; if(vis[now]){ dis=cnt+1-vis[now]; l=vis[now]; } } k=k+1; if(l==0){cout<<"1"<<endl;return 0;} if(k<l){ cout<<mp[k]<<endl; }else{ k=k-l; k%=dis; k+=l; cout<<mp[k]<<endl; } }
E:Colorful Blocks(待补)
F:racket Sequencing(待补)
前ICPC算法竞赛退役选手|现摸鱼ing