牛客多校第二場補題
阿新 • • 發佈:2020-07-19
D-Duration
簽到
F-Fake Maxpooling
先得求lcm矩陣
關於求\(lcm\)矩陣,一種方法是直接暴力列舉每一對\((i,j)\),然後暴力計算\(gcd(i,j),lcm(i,j)=i*j/gcd(i,j)\)
第二種是類似埃氏篩的思想,對於每一對互質的\((i,j)\),都去從1列舉一個k使得\(i*k<=n\) 並且 \(j*k<=m\),然後把每一對\((i*k,j*k)\)的gcd標記為k,這樣篩的效率就很高了(接近線性)
最後得到lcm矩陣的複雜度就是\(O(nm)\),剩下就是求每個k*k的正子矩陣的最大值了
由於是區間最大值,兩次滑動視窗即可(這個題stldeque沒被卡)
#pragma GCC optimize(2) #include<bits/stdc++.h> #define ll long long #define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL); using namespace std; double pi = acos(-1); const double eps = 1e-9; const int inf = 1e9 + 7; const int maxn = 5005; int DP[maxn][maxn]; int A[maxn][maxn]; struct poi { int id; ll num; }; deque<poi>deq; int __gcd(int a, int b) { while (b) { ll tmp = b; b = a % b; a = tmp; } return a; } int main() { int n, m, k; scanf("%d%d%d", &n, &m, &k); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { if (!DP[i][j]) for (int u = 1; u * i <= n && u * j <= m; u++) DP[u * i][u * j] = u, A[u * i][u * j] = i * j * u; } for (int i = 1; i <= n; i++) { deq.clear(); int j = 1; for (int j = 1; j <= m; ++j) { int tmp = A[i][j]; while (!deq.empty() && deq.front().id <= j - k)deq.pop_front(); while (!deq.empty() && tmp > deq.back().num) deq.pop_back(); deq.push_back({ j,tmp }); DP[i][j] = deq.front().num; } } ll ans = 0; for (int j = k; j <= m; ++j) { deq.clear(); for (int i = 1; i <= n; ++i) { int tmp = DP[i][j]; while (!deq.empty() && deq.front().id <= i - k)deq.pop_front(); while (!deq.empty() && tmp > deq.back().num) deq.pop_back(); deq.push_back({ i,tmp }); if (i >= k) ans += deq.front().num; } } printf("%lld\n", ans); return 0; }
C-Cover the Tree
比賽的時候有思路,忘記寫了
先記錄入度為1的點計數為sum,ans就是點數/2上取整;然後從入度不為1的點開始dfs,把每個入度為1的點的dfs記錄下來,把i和sum / 2 + i連線起來就可以將所有的邊覆蓋(不太會證。。。畫圖舉例吧)
#pragma GCC optimize(2) #include<bits/stdc++.h> //#include<cstdio> //#include<iostream> //#include<vector> //#include<cstring> //#include<string> //#include<algorithm> #define ll long long #define fastio {ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);}; using namespace std; double pi = acos(-1); const double eps = 1e-9; const int inf = 1e9 + 7; const int maxn = 1e6 + 10; const ll mod = 998244353; vector<int>G[maxn]; int sum = 0; int n; vector<int>xu; void dfs(int from, int last) { if (G[from].size() == 1) { xu.push_back(from); return; } for (int i = 0; i < G[from].size(); i++) { int to = G[from][i]; if (to != last) dfs(to, from); } } int main() { fastio; cin >> n; for (int i = 1; i < n; i++) { int a, b; cin >> a >> b; G[a].push_back(b); G[b].push_back(a); } for (int i = 1; i <= n; i++) if (G[i].size() == 1) sum++; cout << (sum + 1) / 2 << endl; for (int i = 1; i <= n; i++) if (G[i].size() != 1) { dfs(i, -1); break; } for (int i = 0; i < sum / 2; i++) cout << xu[i] << " " << xu[sum - i - 1] << endl; if (sum & 1) cout << xu[sum / 2 ] << " " << xu[0] << endl; return 0; }
B-Boundary
計算幾何,列舉每一個點i,得到與圓心連線所對的弦對應的弧,利用同弧所對的圓周角相同,再去列舉另一個點j,將∠oji存下來,其中的眾數就是ans
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
double pi = acos(-1);
const double eps = 1e-12;
const int inf = 1e9 + 7;
const int maxn = 2e5 + 10;
int read()
{
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c>'9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar();
return f * x;
}
inline int dcmp(double x)//cmp x with 0
{
if (fabs(x) <= eps)return 0;
return x < 0 ? -1 : 1;
}
inline int cmp(double x, double y)
{
//x>y return 1
//x<y reutrn -1
//x==y return 0
return dcmp(x - y);
}
double max(double x, double y)
{
return dcmp(x - y) > 0 ? x : y;
}
double min(double x, double y)
{
return dcmp(x - y) < 0 ? x : y;
}
struct Point {
double x, y;
Point() {}
Point(double xx, double yy) { x = xx; y = yy; }
Point operator -(Point s) { return Point(x - s.x, y - s.y); }
Point operator +(Point s) { return Point(x + s.x, y + s.y); }
double operator *(Point s) { return x * s.x + y * s.y; }
double operator ^(Point s) { return x * s.y - y * s.x; }
}p[2010];
double len(Point a) { return sqrt(a * a); }
double dis(Point a, Point b) { return len(b - a); }//兩點之間的距離
double cross(Point a, Point b, Point c)//叉乘,a為公共點
{
return (b - a) ^ (c - a);
}
double dot(Point a, Point b, Point c)//點乘 ,a為公共點
{
return (b - a) * (c - a);
}
double angle(Point a, Point b, Point c)//求兩個向量的夾角(餘弦定理),a為公共點
{
return acos(dot(a, b, c) / dis(b, a) / dis(c, a));
}
bool Cmp(double x, double y)
{
if (cmp(x, y) == -1)return 1;
return 0;
}
vector<double>rad;
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
double x, y;
scanf("%lf %lf", &x, &y);
p[i] = { x,y };
}
if (n == 1)
{
printf("1\n");
return 0;
}
Point O = { 0.0,0.0 };
int ans = 1;
for (int i = 1; i <= n; i++)
{
rad.clear();
for (int j = 1; j <= n; j++)
{
if (cross(O, p[i], p[j]) < 0)
rad.push_back(dot(p[j], O, p[i]) / (dis(p[j], p[i]) * dis(p[j], O)));
}
sort(rad.begin(), rad.end(), Cmp);
int size = rad.size();
for (int l = 0, r; l < size; l = r)
{
for (r = l; r < size && cmp(rad[l], rad[r]) == 0; r++);
ans = max(ans, r - l + 1);
}
}
printf("%d\n", ans);
return 0;
}