这场比赛,我写的跟个憨批一样,日常全靠队友
A题
//一开始写了个正向的,用memset每次都把它全都置0,tle16
//后来用vector记录哪几个数用了,tle27
//所以,以后正向遍历不行,就要思考反向的
#include <bits/stdc++.h> using namespace std; const int M = 1e6 + 1; int vis[M];//存储是否负数已经出现过,一旦出现过那个正数就不能出现 const int inf = 1e8; int mi = inf;//用于后面求最靠近的相同数的坐标 int ans[M];//存储最终答案 int f[M]; int a[M];//存储原始数据 int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { cin >> a[i]; } for (int i = n ; i >= 1; i--) {//从后往前遍历 if (a[i] > 0) {//在为正数的情况下 ans[i] = ans[i + 1] + 1;//这一次,等于上一次多加1 f[a[i]] = i;//记录此时的位置,每次找到同一个数,都要更新一下位置,更新成最近的 vis[a[i]]=1;//判断是否已经出现过 } else { if (vis[abs(a[i])] == 0) {//这个数的正数,在后面没有出现过 ans[i] = ans[i + 1] + 1;//直接加1 } else {//在后面已经出现过 mi = min(mi, f[abs(a[i])]);//找到最近的出现的那个相同的数 //这里有一个很有效的技巧 //因为在正常情况下,你要找的是 ans[i] = mi - i; } } } for (int i = 1; i <= n; i++) { printf("%d%c", ans[i], i == n ? '\n' : ' '); } }
B题
//这题我还以为有什么鬼畜技巧,其实就是只要上下两个有一组相等,就构成一组桥,一定是可以连通的,因为左右可以疯狂随意互换
//所以只要顺序输出就好
#include <bits/stdc++.h> using namespace std; const int M = 1e6 + 1; string s1, s2; int c[5]; int main() { cin >> s1 >> s2; for (int i = 0; i < s1.size(); i++) { if (s1[i] == '#' && s2[i] == '.') c[1]++; else if (s1[i] == '.' && s2[i] == '#') c[2]++; else if (s1[i] == '#' && s2[i] == '#') c[3]++; else if (s1[i] == '.' && s2[i] == '.') c[4]++; } if (c[1] && c[2] && c[3] == 0) { cout << "NO" << endl; } else { cout << "YES" << endl; for (int i = 0; i < c[1]; i++) { cout << "#"; } for (int i = 0; i < c[3]; i++) { cout << "#"; } for (int i = 0; i < c[2]; i++) { cout << "."; } for (int i = 0; i < c[4]; i++) { cout << "."; } cout << "\n"; for (int i = 0; i < c[1]; i++) { cout << "."; } for (int i = 0; i < c[3]; i++) { cout << "#"; } for (int i = 0; i < c[2]; i++) { cout << "#"; } for (int i = 0; i < c[4]; i++) { cout << "."; } } }
I题
采用螺旋矩阵的方式是最短的,可以自行模拟一下,只要每转过两次,原本的长度就要减去一个b的长度
#include <bits/stdc++.h> #define ll long long using namespace std; const int M = 1e6 + 1; int main() { ll a, b; cin >> a >> b; ll k = a - b; ll su = k; while (k >= 0) { su += k + k; k -= b; } cout << su << endl; }
L题
//计算几何的题目
//首先找到半径,因为三个圆心是在同一条直线上
//在根据相似三角形的特性求坐标
#include <bits/stdc++.h> using namespace std; const int M = 1e6 + 1; int main() { double x1, x2, y1, y2, r1, r2; cin >> x1 >> y1 >> r1; cin >> x2 >> y2 >> r2; if (x1 > x2) { swap(x1, x2); swap(y1, y2); swap(r1, r2); } double L = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); double r = (r1 + r2 - L) / 2; double x = (L - r2 + r) / L * (x2 - x1) + x1; double y = (L - r2 + r) / L * (y2 - y1) + y1; printf("%.10f %.10f %.10f", x, y, r); }
E题
贪心题,思路就是,先排序,x小,y大。
然后开始遍历,找到x小于原来的坐标y,并且现在的y还是在后面的最大值
不断循环,直到找完。
如果找完后,依旧到不了m,则输出no
#include <bits/stdc++.h> using namespace std; #define ll long long const int M = 1e6 + 1; struct node { int x, y; int id; }p[M]; bool cmp(node a, node b) {//比较函数 if (a.x != b.x) return a.x < b.x; return a.y > b.y; } int n, m; vector<int> q;//数组,存储了最终的位置值 int main() { cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> p[i].x >> p[i].y; p[i].id = i; } sort(p + 1, p + 1 + n, cmp); if (p[1].x != 1) {//如果第一个的x都不是1,那么肯定就不存在1了,可以直接退出了 cout << "NO"; } else { q.push_back(p[1].id);//可以的情况下,推入1的id int now = p[1].y;//记录此时1的右界极限
//这之后的操作都是为了找一个,比now大,且为最大的另一个数的右界,同时左界比now+1小的数 for (int i = 2; i <= n;) { if (p[i].x > now + 1) {//因为是按照顺序排的,理应来说从i=2开始,如果不行,那么之后就没有比他小的左界了,就可以直接退出了 cout << "NO"; return 0; } else { int temp = now, pos = p[i].id;//要开始不断的更细了这里。
//用temp记录原右界,pos记录当前的i的id
//这里举个例子,有3, 10 4,13 而now=4,你肯定先拿了10,又发现13更好 就拿了13,这就是寻找最大的值
while (i <= n && p[i].x <= now + 1) {//如果i在范围内,且当前i的左界符合条件 if (p[i].y > temp) {//如果大于temp,即右界,找最大的那个,就更新 temp = p[i].y; pos = p[i].id; } i++;继续找下一个 } if (temp == now) continue;//如果是没变动的情况下,就不用关 now = temp; q.push_back(pos); } } if (now < m) cout << "NO" << endl; else { cout << "YES" << endl; cout << q.size() << endl; for (int i = 0; i < q.size(); i++) cout << q[i] << ' '; cout << endl; } } }
C题
C题主要是数据范围过大,找到他是如何循环的即可
根据他走点的方式,可知道他在n时刻,走的总长是(n+1)*n/2%p
当n为p时,若p为奇数,那么p+1除以2是可行的,将回到原点,构成一个循环
当p为偶数时,p+1除以2不行,所以把p改为2p,所以极限情况下就是2p,将能循环一次
#include <bits/stdc++.h> using namespace std; #define ll long long const int M = 1e7 + 1; int vis[M]; int main() { ll p, n; cin >> p >> n; ll k=1; ll su = 0; n=min(p*2,n); vis[0]=1; int ans = 1; while (k != n+1) { ll m = (su + k%p) % p; if(vis[m]==0){ ans++; vis[m]++; } if(ans==p) break; su = m; k++; } cout << ans << endl; }