B、Boundary
参考兰子大佬的题解
问题大概就是给你二维平面的n个点,坐标都是整数,问你选取某一个点为圆心(这个点不一定要是给出的n个点中一个)使得在这个点为圆心过原点的情况下覆盖到给出的n点中最多的点,问最多覆盖几个点!
其实知道方法是可以写出来的,比赛的时候最开始看到0/80+……就觉得这玩意不简单,而且英语小白的我一开始没读出加粗的那句话,直接二重枚举认为给出的点才可能是圆心,WA的理所当然。。听说map计数给卡了常数太大了。。用了二元组去排序计算,还有知识点就是知道三个点的平面坐标求圆心坐标。。这玩意直接推式子再用克莱姆法则替换也能算到,涉及线性代数的知识)马上大二了哎嘿。这里用的是兰子大佬的求法,看起来比较好记,而且和克莱姆法则推出来的是差不多的。这样把全部的圆心计算出来再排下序,根据圆心重合的情况下去统计次数,每重合一个圆心说明选取这个圆心覆盖的点就+1,取最大值即可。)果然我的话有待提高
#pragma GCC target("avx,sse2,sse3,sse4,popcnt") #pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math") #include <bits/stdc++.h> using namespace std; #define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) #define all(__vv__) (__vv__).begin(), (__vv__).end() #define endl "\n" #define pai pair<double, double> #define mk(__x__,__y__) make_pair(__x__,__y__) #define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__)) typedef long long ll; typedef unsigned long long ull; typedef long double ld; const int MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; } inline void print(ll x) { if (!x) { putchar('0'); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); } inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; } ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; } inline int lowbit(int x) { return x & (-x); } #define x first #define y second const int N = 2e6 + 7; const double eps = 1e-6; pai s[2005], p[N]; pai yuanxin(pai a, pai b, pai c) { //已知三点求圆心坐标下面有仔细的步骤,用了克莱姆法则 double A1 = 2 * b.x - 2 * a.x, B1 = 2 * a.y - 2 * b.y, C1 = a.y * a.y + b.x * b.x - a.x * a.x - b.y * b.y; double A2 = 2 * c.x - 2 * b.x, B2 = 2 * b.y - 2 * c.y, C2 = b.y * b.y + c.x * c.x - b.x * b.x - c.y * c.y; pai center; center.x = (C1 * B2 - C2 * B1) / (A1 * B2 - A2 * B1); center.y = (A1 * C2 - A2 * C1) / (A1 * B2 - A2 * B1); return center; } int main() { int n = read(), k = 0; for (int i = 1; i <= n; ++i) s[i].x = read(), s[i].y = read(); pai z = { 0,0 }; for (int i = 1; i <= n; ++i) for (int j = i + 1; j <= n; ++j) if (fabs(s[i].x * s[j].y - s[i].y * s[j].x) > eps) { //和原点三点不共线 pai tmp = yuanxin(s[i], s[j], z); p[++k] = tmp; } if (!k) return cout << 1, 0; sort(p + 1, p + 1 + k); int cnt = 1, ans = 1; for (int i = 1; i < k; ++i) if (fabs(p[i].x - p[i + 1].x) < eps and fabs(p[i].y - p[i + 1].y) < eps) ++cnt, ans = max(ans, cnt); //同一个圆心的话,这个圆心统计的点数+1 else cnt = 1; //否则归1,cnt来到算到这个圆心的点这里 for (int i = 1; i <= n; ++i) if (i * (i - 1) == ans * 2) return cout << i, 0; return 0; } /* 通过三个点到圆心距离相等建立方程: (pt1.x-center.x)²-(pt1.y-center.y)²=radius² 式子(1) (pt2.x-center.x)²-(pt2.y-center.y)²=radius² 式子(2) (pt3.x-center.x)²-(pt3.y-center.y)²=radius² 式子(3) 式子(1)-式子(2)得: pt1.x²+pt2.y²-pt1.y²-pt2.x²+2*center.x*pt2.x-2*center.x*pt1.x+2*center.y*pt1.y-2*center.y*pt2.y-=0 式子(2)-式子(3)得: pt2.x²+pt3.y²-pt2.y²-pt3.x²+2*center.x*pt3.x-2*center.x*pt2.x+2*center.y*pt2.y-2*center.y*pt3.y-=0 整理上面的两个式子得到: (2*pt2.x-2*pt1.x)*center.x+(2*pt1.y-2*pt2.y)*center.y=pt1.y²+pt2.x²-pt1.x²-pt2.y² (2*pt3.x-2*pt2.x)*center.x+(2*pt2.y-2*pt3.y)*center.y=pt2.y²+pt3.x²-pt2.x²-pt3.y² 令: A1=2*pt2.x-2*pt1.x B1=2*pt1.y-2*pt2.y C1=pt1.y²+pt2.x²-pt1.x²-pt2.y² A2=2*pt3.x-2*pt2.x B2=2*pt2.y-2*pt3.y C2=pt2.y²+pt3.x²-pt2.x²-pt3.y² 则上述方程组变成一下形式: A1*center.x+B1*center.y=C1; A2*center.x+B2*center.y=C2 联立以上方程组可以求出: center.x = (C1*B2 - C2*B1) / (A1*B2 - A2*B1); center.y = (A1*C2 - A2*C1) / (A1*B2 - A2*B1); (为了方便编写程序,令temp = A1*B2 - A2*B1) */
D、Duration
签到题,没看到关键字同一天直接按60进制进位减掉求绝对值即可。
#pragma GCC target("avx,sse2,sse3,sse4,popcnt") #pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math") #include <bits/stdc++.h> using namespace std; #define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) #define all(__vv__) (__vv__).begin(), (__vv__).end() #define endl "\n" #define pai pair<int, int> #define mk(__x__,__y__) make_pair(__x__,__y__) typedef long long ll; typedef unsigned long long ull; typedef long double ld; const int MOD = 1e9 + 7; const ll INF = 0x3f3f3f3f; inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; } inline void print(ll x) { if (!x) { putchar('0'); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); } inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; } ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; } inline int lowbit(int x) { return x & (-x); } const int N = 1e5 + 7; int main() { int h1, h2, m1, m2, s1, s2; scanf("%d:%d:%d", &h1, &m1, &s1); scanf("%d:%d:%d", &h2, &m2, &s2); int ans1 = h1 * 3600 + m1 * 60 + s1, ans2 = h2 * 3600 + m2 * 60 + s2; printf("%d", abs(ans2 - ans1)); return 0; }
F、Fake Maxpooling
#pragma GCC target("avx,sse2,sse3,sse4,popcnt") #pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math") #include <bits/stdc++.h> using namespace std; #define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) #define all(__vv__) (__vv__).begin(), (__vv__).end() #define endl "\n" #define pai pair<int, int> #define mk(__x__,__y__) make_pair(__x__,__y__) #define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__)) typedef long long ll; typedef unsigned long long ull; typedef long double ld; inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; } inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op) putchar(op); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); if (op) putchar(op); } inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; } ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; } inline int lowbit(int x) { return x & (-x); } const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} }; const int MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; const int N = 5000 + 7; int a[N][N], q[N], b[N]; int GCD[N][N]; int n, m, k; void find_row(int j) { int head = 1, tail = 0; for (int i = 1; i <= n; ++i) { while (head <= tail and q[head] + k <= i) ++head; while (head <= tail and a[i][j] > a[q[tail]][j]) --tail; q[++tail] = i; if (i >= k) b[i - k + 1] = a[q[head]][j]; } for (int i = 1; i <= n - k + 1; ++i) a[i][j] = b[i]; } void find_col(int i) { int head = 1, tail = 0; for (int j = 1; j <= m; ++j) { while (head <= tail and q[head] + k <= j) ++head; while (head <= tail and a[i][j] > a[i][q[tail]]) --tail; q[++tail] = j; if (j >= k) b[j - k + 1] = a[i][q[head]]; } for (int j = 1; j <= m - k + 1; ++j) a[i][j] = b[j]; } int main() { n = read(), m = read(), k = read(); for (int i = 1; i <= n; ++i) // O(n*m)预处理矩阵 for (int j = 1; j <= m; ++j) if (!GCD[i][j]) for (int k = 1; i * k <= n and j * k <= m; ++k) GCD[i * k][j * k] = k, a[i * k][j * k] = i * j * k; for (int i = 1; i <= m; ++i) find_row(i); //固定列把这一列中近可能大的行放在前面 for (int i = 1; i <= n; ++i) find_col(i); //之前基础上固定行把尽可能大的列放在前面 ll ans = 0; for (int i = 1; i <= n - k + 1; ++i) for (int j = 1; j <= m - k + 1; ++j) ans += a[i][j]; print(ans); return 0; }