A. Mezo Playing Zoma
题意:
给你一串指令,只包含(L,R)表示向左向右移,但有些指令可能不起作用,问最后能到的位置有多少种可能
思路:
我们分析一下就可以知道,最终的结果时L的数目+R的数目+1。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; int main() { string t; int n; cin >> n; cin >> t; // set<int> s; //s.insert(0); int l = 0,r = 0; for(int i = 0;i<n;++i) { if(t[i]=='L') ++l; else ++r; } cout << r+l+1 << ' '; return 0; }
B. Just Eat It!
题意:
给你一组数字,问能不能找到一个子区间[l,r],它的和大于等于[1,n],但[l,r]不能等于[1,n]。
如果可以,输出No,否则输出YES
思路:
求取区间和,很明显,我们可以直接用尺取法来解决这个问题。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 1e5+10; LL num[maxn]; int main() { int t; cin >> t; while(t--) { int n; LL tmp = 0,sum = 0; cin >> n; for(int i = 1; i<=n; ++i) { cin >> num[i]; sum+=num[i]; } int l = 1,r = 1,ml = 1,mr = 1; LL ans = num[1],max_ans = num[1]; for(int i =2; i<=n; i++) { //cout << i << ": " << num[i] << " " << ans << endl; if(ans+num[i]>num[i]) { ans+=num[i]; ++r; } else { ans= num[i]; l = r = i; } if(ans>max_ans) { //cout << 1 << endl; max_ans = ans; ml = l; mr = r; } if(max_ans>=sum) break; } if((ml==1&&mr==n)||max_ans<sum) { printf("YES "); } else { printf("NO "); } } return 0; }
C. Fadi and LCM
题意:
给你一个数字X,让你求一对数a,b,使得LCM(a,b) =X并且max(a,b)最小
思路:
由上可以推断出,a,b一定X的因子,因此,枚举X的(互素)因子进行计算即可。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; LL a = 1,b=1; void solve(LL x) { //bool flag = false; LL max_x = x; LL a = 1, b = x; for(LL i = 1;i*i<=x;++i) { if(x%i==0) { if(__gcd(i,x/i)==1&&max(i,x/i)<max_x) { max_x = max(i,x/i); a = i; b = x/i; } } } cout << a << " " << b << endl; } int main() { LL x; cin >> x; solve(x); return 0; }
D. Dr. Evil Underscores
题意:
给你一组数,让你设定一个数X,使得X异或数组中每一个数的最大值最小,并输出这个最小值。
思路:
考虑二进制来解决当前问题,由题意可知,最多有30位,我们可以将每一个数展开为二进制形式。接下来从高位到低位,枚举每一位,假如当前位全是1或0,根据异或的性质,当前为要去与之相反的值,这对于最后的结果的贡献值是0,假如这一位有0有1,那么我们就需要两种情况都枚举下,但是无论哪种情况,对于最后答案的贡献都是1<<k(k表示是当前的第几位)
代码:
#include <bits/stdc++.h> using namespace std; int solve(int k,vector<int> p) { if(p.size()==0||k<0) return 0; vector<int>p1,p2; for(int i = 0;i<p.size();i++) { if((p[i]>>k)&1) p1.push_back(p[i]); else p2.push_back(p[i]); } if(p1.size()==0) return solve(k-1,p2); else if(p2.size()==0) return solve(k-1,p1); else return (1<<k)+min(solve(k-1,p2),solve(k-1,p1)); } int main() { int n; scanf("%d",&n); vector<int> p(n); for(int i = 0;i<n;++i) scanf("%d",&p[i]); printf("%d ",solve(29,p)); return 0; }
E. Delete a Segment
题意:
给你n条线段,求删除一条线段后,最多能有多少条线段(有交集的线段算是一条)。
思路:
可以参考下下面的博客
https://www.cnblogs.com/AaronChang/p/12192295.html
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 4e5+10; pair<ll,ll>p[maxn]; int cnt[maxn]; int main() { int t; cin >> t; while(t--) { int n; cin >> n; for(int i = 1;i<=n;++i) { ll l,r; cin >> l >> r; p[2*i-1] = make_pair(l,-i); p[2*i] =make_pair(r,i); cnt[i] =0; } sort(p+1,p+2*n+1); int ans = 0; multiset<int> s; for(int i = 1;i<=2*n;++i) { if(p[i].second<0) s.insert(-p[i].second); else { s.erase(s.find(p[i].second)); } if(s.size()==0) ans++; if(s.size()==1&&p[i].second>0&&p[i+1].second<0&&p[i+1].first>p[i].first) { cnt[*s.begin()]++; // cout << *s.begin() << endl; } if(s.size()==1&&p[i].second<0&&p[i+1].second>0) { cnt[*s.begin()]--; } } int t =-1; for(int i =1;i<=n;++i) t = max(t,cnt[i]); cout << ans+t << endl; } return 0; }