https://ac.nowcoder.com/acm/contest/893#question
湘潭大学的校赛 断断续续的作终于ak了 看了不少题解(菜就直说)
A Who's better?
签到题
#include<bits/stdc++.h> using namespace std; int main() { int n1,n2,t1,t2,s1,s2; cin>>n1>>t1>>s1; cin>>n2>>t2>>s2; if(n1>n2) { cout<<1; return 0; } if(n1<n2) { cout<<2; return 0; } if(t1<t2) { cout<<1; return 0; } if(t1>t2) { cout<<2; return 0; } if(s1<s2) { cout<<1; return 0; } if(s1>s2) { cout<<2; return 0; } cout<<"God"; }
B Number
也是水题,直接模拟:
#include <bits/stdc++.h> using namespace std; int main(){ int t; cin>>t; while(t--){ int n; cin>>n; int ans=0; while(n>1){ ans++; if(n%10==0) n/=10; else n+=1; } cout<<ans<<endl; } return 0; }
C Math Problem
打表发现a为等差数列,公差为192(其实可以推出来的,但是我懒)
#include<bits/stdc++.h> using namespace std; int main() { long long int t,l,r,sum; cin>>t; while(t--) { cin>>l>>r; if((l-1)%192!=0) l=l+192-(l-1)%192; r=r-(r-1)%192; sum=(l+r)*((r-l)/(192)+1)/2; cout<<sum<<endl; } }
D Stone
这个题我一开始想到的是之前在洛谷做的一道题 仔细看一下又有不同 把握两个条件:第一是任意的两堆石子都可以合并 第二 是合并的时候耗费的体力由小的那一堆石子决定
我们假设有3堆石子 重量分别为 1 3 5
那么如果1和3先合并 耗费1点体力 然后在和5合并 那么耗费4点体力 总共耗费5点体力
但是如果3和5先合并 那么耗费3点体力 再和1合并 那么就耗费1点体力 一共耗费4点体力
两种选择的根本在于 第一种选择把第一堆石子的重量多累积了一次 这就是从小到大合并的弊端
所以我们要从大到小合并 这样所耗费的体力 就是石子重量的总和-最重的石子
#include <bits/stdc++.h> using namespace std; const int N=1e4+5; typedef long long ll; int a[N]; int main(){ int t; cin>>t; while(t--){ int n; cin>>n; for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+1+n); ll ans=0; for(int i=1;i<=n-1;i++){ ans+=a[i]; } cout<<ans<<endl; } return 0; }
E Watermelon
要保证lililalala打扫卫生 就必须让别人吃西瓜的时候有西瓜能吃 在lililalala吃的时候没有西瓜可吃(这不是废话嘛........)
但是每个人吃的西瓜数是一个区间的(1,a[i]),所以我们维护一个区间(l,r) 代表当前能吃的西瓜数 对于每一个非lililalala的人 因为最少可以只吃1个 那么就让r--,因为最多可以吃a[i]个 就让l-=a[i]
而对于lililalala 因为他只会吃a[i]个 所以l和r都要-a[i]
当对于一个非lililalala人来说 如果r<=0,代表前面的人再怎么节约着吃也没得吃了.....就是NO
当对于lililalala来说 如果l<=0,代表前面的人疯狂吃 就可以让lililalala没得吃 那就是YES
#include<bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { int n,m,i,a[100005],lb=0,ladd=0,l,r; cin>>n>>m; for(i=0;i<n;i++) { cin>>a[i]; if(a[i]>lb) { lb=a[i]; ladd=i; } } l=m; r=m; for(i=0;;i=(i+1)%(n)) { if(i==ladd) { if(l<=0) { cout<<"YES"<<endl; break; } else { l-=a[i]; r-=a[i]; } } else { if(r<=0) { cout<<"NO"<<endl; break; } else { r-=1; l-=a[i]; } } } } }
F Black & White
就是求 包含m个1的最长0串 和 包含m个0的最长1串 的较大值
在纸上模拟一下或者debug一下就理解了
#include <bits/stdc++.h> using namespace std; #define ll long long char s[100005]; int n,m; int fun(char ch) { int cnt=0,ans=0; for(int i=0,j=0;i<n;i++){ if(s[i]==ch){ if(cnt<m) cnt++; else{ while(s[j++]!=ch); } } ans=max(ans,i-j+1); } return ans; } int main() { int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); scanf("%s",s); printf("%d\n",max(fun('0'),fun('1'))); } return 0; }
G Truthman or Fakeman
如果A说B是Truthman 那么A和B是同一个团体
如果A说B是Fakeman 那么A和B是不同的两个团体
只要将较大的那个定义为Truthman就好了
用dfs遍历连通块
如果一开始设为Truthman的团体较小 那就再dfs一遍取反
#include<iostream> #include<vector> #include<cstring> using namespace std; typedef pair<int,int> pr; const int MAX_N=1e5+5; int n,m,T; int Sum,s,p; int res[MAX_N]; vector<pr> e[MAX_N]; bool boo[MAX_N]; void DFS(int u,int pre); void DFS1(int u,int pre); int main() { ios::sync_with_stdio(false); cin>>T; while(T--){ p=1; memset(res,-1,sizeof(res)); memset(boo,0,sizeof(boo)); cin>>n>>m; for(int i=0;i<=n;++i) e[i].clear(); int u,v,w; for(int i=0;i<m;++i) { cin>>u>>v>>w; e[u].push_back({v,w}); e[v].push_back({u,w}); } for(int i=1;i<=n&&p==1;++i) if(res[i]==-1){ Sum=s=0; boo[i]=true; res[i]=1; DFS(i,0); if(s+s<Sum) DFS1(i,0); } if(p==1){ for(int i=1;i<=n;++i) cout<<res[i]; cout<<endl; }else cout<<-1<<endl; } return 0; } void DFS(int u,int pre) { ++Sum; if(res[u]==1) ++s; int v,w; for(auto c:e[u]) if(c.first!=pre){ if(p==-1) break; v=c.first; w=c.second; if(res[v]!=-1){ if((w==1&&res[v]!=res[u])||(w==0&&res[v]+res[u]!=1)){ p=-1; break; } }else{ if(w==1){ if(res[v]!=-1&&res[v]!=res[u]) p=-1; res[v]=res[u]; }else{ if(res[v]!=-1&&res[v]+res[u]!=1) p=-1; res[v]=(res[u]+1)%2; } DFS(v,u); } } } void DFS1(int u,int pre) { res[u]=(res[u]+1)%2; for(auto c:e[u]) if(c.first!=pre&&!boo[c.first]){ boo[c.first]=true; DFS1(c.first,u); } }
H Chat
分组dp
题意转化为要求女神生气度为K时能偷懒最长的时间
dp首先要有代价和价值 代价是鸽女神i个小时 价值就是鸽女神i个小时所能换来的最大时间
代价是要先求一遍的 具体看代码吧
#include<bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { int n,m,k,w,i,j,vul[205][205],p[205],dp[205][205],it[205]; memset(vul,0,sizeof(vul)); memset(p,0,sizeof(p)); memset(dp,0,sizeof(dp)); memset(it,0,sizeof(it)); scanf("%d%d%d",&n,&m,&k); int sum=n*m; for(i=1;i<=n;i++) { char a[205]; scanf("%s",a+1); for(j=1;j<=m;j++) { if(a[j]=='0') p[j]=p[j-1]; else { p[j]=p[j-1]+1; it[i]++; } } vul[i][it[i]]=m; for(j=1;j<=m;j++) for(w=j;w<=m;w++) vul[i][it[i]-(p[w]-p[j-1])]=max(vul[i][it[i]-(p[w]-p[j-1])],m-(w-j+1)); } for(i=1;i<=n;i++) for(j=0;j<=it[i];j++) for(w=k;w>=j;w--) { dp[i][w]=max(dp[i][w],dp[i-1][w-j]+vul[i][j]); } cout<<sum-dp[n][k]<<endl; } }