Goodbye 2019
QAQ:这场比赛在凌晨,于是乎没打。开了重现,A掉三题,这大概就是我现在的水平了吧
A. Card Game
简单题,看谁的牌最大
#include<bits/stdc++.h> using namespace std; int a[105],b[105]; int main() { int T; cin >> T; while(T--) { int n,k1,k2; cin >> n >> k1 >> k2; for(int i = 0;i<k1;i++) { cin >> a[i]; } for(int i =0;i<k2;++i) cin >> b[i]; bool flag = false; for(int i = 0;i<k1;++i) { if(a[i]==n) { flag = true; break; } } if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }
B. Interesting Subarray
简单题,思路就是比较相邻的两个数,如果之差>1,则代表这是符合题意的解,如果没有,则证明整个数组不存在解。
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5+10; int num[maxn]; int main() { int T; cin >> T; while(T--) { int n; cin >> n; for(int i = 0;i<n;i++) { cin >>num[i]; } bool flag = false; int l = 0,r = 0; for(int i =0;i<n-1;i++) { if(abs(num[i]-num[i+1])>1) { flag =true; l = i,r = i+1; break; } } if(!flag) printf("NO\n"); else { printf("YES\n"); printf("%d %d\n",l+1,r+1); } } return 0; }
C. Make Good
简单题,我们可以先把等式左边算出来,记为a,右边算出来,记为b,根据异或的性质,先向数组中添加一个数b,左边变成a+b,右边变成0,再加入数a+b,即可符合题意,这两个数也就是所求。
#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; cin >> n; for(int i = 0;i<n;++i) { cin >> num[i]; } LL ans = num[0],ans2 = num[0]; for(int i = 1;i<n;i++) { ans+=num[i]; ans2^=num[i]; } if(ans == ans2*2) { printf("0\n\n"); } else { cout << 2 << endl; cout << ans2 << " " << ans+ans2 << endl; } } return 0; }
Ps: 以下题解均来自cf的官方题解
D. Strange Device
交互题,这也是我第一次做交互题,很懵,题没读懂。
题意:给你一个有n个元素的数组a,并保证其中的元素两两不同,你有一个机器,这个机器接受输入k个输入的位置,返回在这k个位的数经过排序以后的m-th的数在a里的位置和他的值。让你通过不超过n次的询问,计算出m的大小。
思路:
稳定查询k+1次,每次用第k+1的数替换1-k+1的一个数,设1-k+1中的第m-th大的数为 a,第m+1-th为b,则由题意可知,b会出现m次,a则会出现k+1-m次,因此,记录每次查询返回的值,其中最大的是b,记录一下b的出现次数,即可以计算出m
#include <bits/stdc++.h> using namespace std; int main() { ios_base::sync_with_stdio(0); cin.tie(nullptr); int n, k; cin>>n>>k; vector<int> elements; for (int i = 1; i<=k+1; i++) { cout<<"? "; for (int j = 1; j<=k+1; j++) if (j!=i) cout<<j<<' '; cout<<endl; int pos, el; cin>>pos>>el; elements.push_back(el); } int maxx = elements[0]; for (auto it: elements) maxx = max(maxx, it); int m = 0; for (auto it: elements) if (it==maxx) m++; cout<<"! "<<m<<endl; }
E. Divide Points
题意:将给定点集分为两部分,设属于同一部分的任意两点的距离为集合A,属于不同部分任意两点的距离为集合B,请输出其中一个满足题意的集合。
思路:我们可以根据奇偶性把点分为A00,A01,A10,A11 这四类,先考虑第一种分类假如A00 +A11>0&&A01 +A10>0我们可以证明 集合A中的数全是偶数,集合B中的数全是奇数,假如第一类分类不行,则证明剩下的全是A00和A11 或者全是,A01,A10 则可进行第二种分类,假如是第一种情况 则可以证明集合A中全是可以整除4,集合B中全是除4余2的数,如果是第二种情况,也可以证明集合A中全是可以整除4,集合B中全是除4余2的数。如果第二种分类也不成立,则证明当前条件下仅存在上述四种情况下的一种,所以我们可以找出他们属于哪一类点,并且针对于这个对点进行坐标变换,重复上述操作,直到找到解。
#include <bits/stdc++.h> using namespace std; const int maxn = 1e3+10; struct Node { int x,y; Node(int _x = 0,int _y = 0):x(_x),y(_y) {} }; Node Point[maxn]; int cnt[3][3] = {0}; int main() { int n; scanf("%d",&n); for(int i = 0; i<n; i++) { scanf("%d %d",&Point[i].x,&Point[i].y); Point[i].x+=int(1e6); Point[i].y+=int(1e6); } while(true) { memset(cnt,0,sizeof(cnt)); for(int i = 0; i<n; ++i) { int x = Point[i].x,y = Point[i].y; ++cnt[x%2][y%2]; } if(cnt[0][0]+cnt[1][1]>0&&cnt[0][1]+cnt[1][0]>0) { printf("%d\n",cnt[0][0]+cnt[1][1]); int cur = 0; for(int i = 0; i<n; i++) { int x = Point[i].x,y = Point[i].y; if((x%2==0&&y%2==0)||(x%2==1&&y%2==1)) { if(cur==0) printf("%d",i+1); else printf(" %d",i+1); ++cur; } } return 0; } if(cnt[0][0]+cnt[1][0]>0&&cnt[1][1]+cnt[0][1]>0) { printf("%d\n",cnt[0][0]+cnt[1][0]); int cur = 0; for(int i = 0; i<n; i++) { int x = Point[i].x,y = Point[i].y; if((x%2==0&&y%2==0)||(x%2==1&&y%2==0)) { if(cur==0) printf("%d",i+1); else printf(" %d",i+1); ++cur; } } return 0; } int x = 0; int y = 0; for(int i = 0; i<2; ++i) { for(int j = 0; j<2; ++j) { if(cnt[i][j]) { x = i; y = j; break; } } } for(int i = 0; i<n; i++) { Point[i].x = (Point[i].x-x)/2; Point[i].y = (Point[i].y-y)/2; } // return p; } return 0; }
G.Subset with Zero Sum
将表达式变化可以得到 1<= i-ai<=n,因此我们可以将其转化为一个有向图,对于每一个点i,都连接一条边到点(i-ai),我们最后能在这个图上找到一个有向环。这条环上的所有点之和必定为0,可以列出等式来证明。
#include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; vector<int> a(n+1); for(int i = 1;i<=n;++i) cin >> a[i]; vector<bool> visited(n+1); int cur = 1; while(!visited[cur]) { visited[cur] = true; cur = cur -a[cur]; } vector<int> ans = {cur}; int cur1 = cur - a[cur]; while(cur1!=cur) { ans.push_back(cur1); cur1 = cur1-a[cur1]; } cout << ans.size() << '\n'; for(auto it:ans) cout << it << " "; cout << '\n'; } int main() { ios_base::sync_with_stdio(0); cin.tie(nullptr); int t; cin >> t; for(int i = 0;i<t;i++) solve(); return 0; }