学军奋斗组训练contest1
T1:The Fair Nut and Elevator
这题说实在的还是折腾了我不少时间,因为本蒟蒻可怜的英语能力。
题意:
有N(n <= 100)个楼层,每层楼里住着ai 个人,其中有一台奇怪的电梯管理着这栋楼上上下下。它固定停在某一层(由你决定),当有人要使用时依次到达起点和终点最后回来(每个人只会从一楼到自己的,或者从自己的到1层,每天上下班共一个来回),才会进行下一轮工作,且同时只会运输一个人。(真省电。。。。。。)为了省电,于是想问你当电梯停在任意楼层时,最少需要跑多少楼层。
思路的话,直接暴力枚举电梯固定停的楼层,在再计算,n2无压力水过。
Select Code #include<bits/stdc++.h> using namespace std; int a[101]; int main() { int n; cin >> n; for(int i = 1;i <= n;i++) { int x; scanf("%d",&x); a[i] = x; } int ans = 1000000001; for(int i = 1;i <= n;i++) { int sum = 0; for(int j = 1;j <= n;j++) { sum += 2*a[j]*(abs(j-i)+j-1+i-1); } ans = min(ans,sum); } cout << ans; return 0; }
T2:Kvass and the Fair Nut
很水的二分题,但是我考试时打挂了。没办法,只能糊式子。
题意:
有n(n <= 103)杯水,其中第i杯水有ai(ai <= 109)份水,你先在需要从这些杯子中倒出总共s(s <= 1012)份的水,使含有最少水的杯子含水最多。求这个值。
其实这个式子也很好糊,考虑一下一个贪心思路,就是尽可能使所有的杯子里含的水更接近。于是我们先算出来操作结束后的总水量,然后除以杯子的数量,但是要注意,答案不能小于初始最小水量。
#include<bits/stdc++.h> using namespace std; long long a[10001];//记得一定要long long 不然会挂 long long n,s; int main() { cin >> n >> s; long long mx = 0; long long sum = 0; long long mn = 1000000000000; for(int i = 1;i <= n;i++) { scanf("%lld",&a[i]); mn = min(a[i],mn); sum += a[i]; } if(sum < s) { puts("-1"); return 0; } cout << min(mn,(sum-s)/n); return 0; }
T3:The Fair Nut and String
一道典型的结论+字符串题,题目还是比较新颖的。
题意:
有一字符串(s.length <= 105),现在你需要求出所有满足条件的location(地址)的子序列。
它需要满足以下条件:
1、所有location对应字符都是‘a’;
2、所有location之间都至少有一个location对应‘b’;
考虑当你遇到一个b的时候,那么所有在这个b之前就可以满足的子序列都可以加上这个b后面所有出现的a中的一个匹配。
#include<bits/stdc++.h> using namespace std; const int mod = 1e9+7; char s[100001]; int main() { scanf("%s",s+1); int len = strlen(s+1); long long ans = 1,cnt = 1; for(int i = 1;i <= len;i++) { if(s[i] == 'a') cnt++; else if(s[i] == 'b') { ans = (ans*cnt)%mod; cnt = 1; } } ans = (ans*cnt) % mod; cout << ans-1 << endl; return 0; }
T4:The Fair Nut and the Best Path
一道简单的树型DP题,只要想到了应该还是挺好写的。
题意:
有一棵有n (n <= 3*105)个点的树,其中所有的边都是负权的,点是正权的。要求一个权值最大的简单路径。
考虑树上任意一条简单路径必定是从一个点一直向子树延伸下去。假设任意一个点为始祖的路径,使简单路劲权值最大,那么一定是有最大和次大的两条子链和当前祖先形成的。这个子链大小可以用最大的子链DP直接转移,但是注意如果子链为负,那么不转移,直接使用该点的权值。
#include<bits/stdc++.h> using namespace std; int val[300005]; long long f[300005],dp[300005]; vector <pair <int, int> > vec[300005]; int n; long long ans = 0; void dfs(int u,int fa) { f[u] = val[u]; dp[u] = val[u]; long long mx = 0,Mx = 0; for(int i = 0;i < vec[u].size();i++) { if(vec[u][i].first == fa) continue; dfs(vec[u][i].first,u); if(mx < f[vec[u][i].first] - vec[u][i].second) { Mx = mx; mx = f[vec[u][i].first] - vec[u][i].second; } else if(Mx < f[vec[u][i].first] - vec[u][i].second) { Mx = f[vec[u][i].first] - vec[u][i].second; } } dp[u] += mx; dp[u] += Mx; f[u] += mx; ans = max(max(ans,dp[u]),f[u]); } int main() { cin >> n; for(int i = 1;i <= n;i++) { scanf("%d",&val[i]); } int u,v,w; for(int i = 1;i < n;i++) { scanf("%d%d%d",&u,&v,&w); vec[u].push_back(make_pair(v,w)); vec[v].push_back(make_pair(u,w)); } dfs(1,-1); cout << ans << endl; return 0; }
T5:The Fair Nut and Strings
这题好多同机房(当然是最差的机房,我这么菜)的人都卡在这。但是我好想没什么压力就糊出了结论水过了。
有两个长度为n(n <= 5*105)的“ab”字符串,其中的k个最多有多少前缀和。
这题其实仔细思考一下只要二进制按位相减就好了。
#include<bits/stdc++.h> using namespace std; int main() { long long n,k; cin >> n >> k; string s,t; cin >> s >> t; long long ans = 0; long long suma = 0,sumb = 0; for(int i = 0;i < n;i++) { long long now; suma *= 2; sumb *= 2; if(s[i] == 'b') suma++; if(t[i] == 'b') sumb++; now = sumb - suma + 1; if(now >= k) { ans += (n-i)*k; break ; } ans+=now; } cout << ans << endl; return 0; }