比赛链接

A

题解

知识点:图论,dp。

暴力建图,连接所有点的双向通路,除了原点是单向的,并且把路径长度作为权值。

随后,从原点出发(\(f[0] = 0\),其他点负无穷,保证从原点出发),按照权值从大到小(大的先走小的后走,相等属于同一阶段,满足拓扑序)进行dp。

对于路径 \((u,v)\) 的状态转移方程是 \(g[v] = max(g[v],f[u]+1)\) ,其中 \(f,g\) 分别存储上一次结果和这一次结果,做到滚动数组节省空间,随后把 \(g\) 还给 \(f\),下次dp前把 \(g\) 初始化负无穷。

最后,找到所有点的最大值。

时间复杂度 \(O(n^2)\)

空间复杂度 \(O(n^2)\)

代码

#include <bits/stdc++.h>

using namespace std;

struct node {
int u, v, w;
}; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
pair<int, int> p[2007];
for (int i = 1;i <= n;i++) {
int u, v;
cin >> u >> v;
p[i] = { u,v };
}
vector<node> e;
for (int i = 0;i <= n;i++)///暴力连边,只从原点出发
for (int j = 1;j <= n;j++)
if (i != j)e.push_back({ i,j,(p[i].first - p[j].first) * (p[i].first - p[j].first) + (p[i].second - p[j].second) * (p[i].second - p[j].second) });
sort(e.begin(), e.end(), [&](node a, node b) {
return a.w > b.w;
});///从大到小距离走
vector<int> f(n + 1, -2e9), g(n + 1, -2e9);
int i = 0, j = 0;
f[0] = 0;///解锁原点
while (i < e.size()) {
vector<node> t;
while (j < e.size() && e[i].w == e[j].w) t.push_back(e[j++]);///把下一个大小的边都加入
for (auto ed : t) g[ed.v] = -2e9;///初始化
for (auto ed : t) g[ed.v] = max(g[ed.v], f[ed.u] + 1);///更新到下一个点吃到最多的数量
for (auto ed : t) f[ed.v] = max(g[ed.v], f[ed.v]);///滚动
i = j;
}
cout << *max_element(f.begin(), f.end()) << '\n';
return 0;
}

B

题解

知识点:二分,贪心,排序。

答案单调是可以二分的,所以优先考虑二分。发现对于一个答案要选择最便宜的去验证答案,因此每次需要对序列排序(因为排序规则和答案有关),满足关系式:

\[a_{val} + ka_{id} < b_{val} + kb_{id}
\]

取 \(k\) 个如果价值总和小于等于钱数,证明答案可行。

时间复杂度 \(O(n\log^2n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; int n, m;
struct node {
ll val;
ll id;
}a[100007]; bool check(int mid) {
sort(a + 1, a + n + 1, [&](node a, node b) {
return a.val + mid * a.id < b.val + mid * b.id;
});
ll sum = 0;
for (int i = 1;i <= mid;i++) sum += a[i].val + mid * a[i].id;
return sum <= m;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1;i <= n;i++) cin >> a[i].val, a[i].id = i;
int l = 0, r = n;
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) l = mid + 1;
else r = mid - 1;
}
cout << r << '\n';
return 0;
}

C

题解

知识点:思维。

对某位Y/N数进行分类讨论,如下列表格:

YES数/NO数 0 1 >1
0 -1 -1/0 0
1 -1/1 -1 0
>1 1 1 -1

存在四种情况能确定,两种可能确定,剩下三种不确定直接 \(-1\)。

确定的四种:

  1. Y > 1且N = 0,不可能是错误询问,直接确定为 \(1\)。
  2. N > 1且Y = 0,同上确定为 \(0\) 。
  3. Y > 1且N = 1,确定唯一错误询问,并确定为 \(1\)。
  4. N > 1且Y = 1,同上确定为 \(0\) 。

可能确定的两种:

  1. Y = 1且N = 0,最终错误询问被发现时可确定为 \(1\) ,否则不确定,因此将此类计数,最终判断这种情况。
  2. N = 1且Y = 0,同上可能确定为 \(0\) 。

不确定的三种:

  1. Y = 0且N = 0,显然不确定。
  2. Y = 1且N = 1,发现错误询问,但依然不确定。
  3. Y > 1且N > 1,错误询问超额。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

struct bit {
int y, n;
}a[100007]; bool ans[100007]; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
int x;
string s;
for (int i = 1;i <= 3 * n;i++) {
cin >> x >> s;
if (s == "YES") a[x].y++;
else a[x].n++;
}
bool fault = false;
bool ok = true;
int cnt = 0;
for (int i = 0;i < n;i++) {
if (a[i].y > 1 && a[i].n == 0) ans[i] = 1;
else if (a[i].y == 0 && a[i].n > 1) ans[i] = 0;
else if (!fault && a[i].y > 1 && a[i].n == 1) ans[i] = 1, fault = 1;
else if (!fault && a[i].y == 1 && a[i].n > 1) ans[i] = 0, fault = 1;
else if (a[i].y == 1 && a[i].n == 0) ans[i] = 1, cnt++;
else if (a[i].y == 0 && a[i].n == 1) ans[i] = 0, cnt++;
else ok = false;
}
if (!ok || !fault && cnt) cout << -1;
else for (int i = 0;i < n;i++) cout << ans[i];
cout << '\n';
return 0;
}

D

题解

知识点:树形dp。

题目要求,树中满足度为 \(1\) 的节点的权值都相同(0/1)的连通子图个数。

因为全为 \(0\) 和全为 \(1\) 两种情况其实解决方法一样,所以可以同一个方法跑两次即可。

考虑度为 \(1\) 的节点颜色为 \(flag\) 。设 \(dp[i]\) 表示为以编号 \(i\) 的节点为根的子树的方案数。对于根 \(u\) 及其子节点 \(v_i\) ,每个子节点 \(v_i\) 都有 \(dp[v_i]\) 种选择方案使得以 \(v_i\) 为根的子树符合条件,加上不选 \(v_i\) 分支的一种,共有 \(dp[v_i] + 1\) 种方案。对所有子节点 \(v_i\) ,都可以独立的选和不选,所以进行乘法原理的运算,得到选择子节点 \(v_i\) 的所有方案数为 \(\prod (dp[v_i]+1)\) 。

但有一种情况是所有子节点都不选,只留个根。这种方案会使这个节点成为一个度为 \(1\) 的点(因为是子树),颜色必须要符合 \(flag\) 才可以作为一种方案。因此这种情况要特判,故 \(dp[u] = \prod (dp[v_i]+1) - 1 + [a[u] == flag]\) 。

接下来是记录答案,如果 \(a[u] = flag\) ,则作为一个独立的以 \(u\) 为根的树(不是别的节点的子树)的所有方案和是子树的所有方案 \(dp[u]\) 是等价的,因为 \(u\) 无论如何都符合条件;如果 \(a[u] \neq flag\) ,则作为一个独立树,当只选了一个子节点的情况是不可行的,此时根节点 \(u\) 是度为 \(1\) 的,与 \(dp[u]\) 的情况不同(因为是子树,\(u\) 只有在什么都不选的情况才会度为 \(1\)),因此要从 \(dp[u]\) 中减去 \(\sum dp[v_i]\) 。

值得注意的是,无论 \(a[u]\) 是否同色,当其本身成为一个只有一个节点的图时,都是满足条件的。这种情况其实已经算在了 \(a[u] = flag\) 中 \(dp[u]\) 的一种里,不需要额外计算,否则会重复。

无根树可以以任何节点为根,因此从 \(1\) 开始没什么问题。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

const int mod = 1e9 + 7;
bool a[300007];
vector<int> g[300007];
bool flag;
int dp[300007];
int ans; void dfs(int u, int fa) {
int sum = 0, mul = 1;
for (int v : g[u]) {
if (v == fa) continue;
dfs(v, u);
mul = 1LL * mul * (dp[v] + 1) % mod;///(子节点方案+不选子节点的一个方案)进行乘法原理
sum = (0LL + sum + dp[v]) % mod;///只选了一个子节点的方案数
}
dp[u] = (mul - 1 + (a[u] == flag)) % mod;///mul减去一个子节点都不选的可能加上自己可能符合要求的可能
if (a[u] == flag) ans = (0LL + ans + dp[u]) % mod;///当前节点符合要求,答案加上dp[u]即可
else ans = (0LL + ans + dp[u] - sum + mod) % mod;///当前节点不符合要求,则不能成为度为1的节点,减去选一个子节点的所有方案
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1;i <= n;i++) {
char ch;
cin >> ch;
a[i] = ch - '0';
}
for (int i = 1;i <= n - 1;i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
flag = 1;
dfs(1, 0);
flag = 0;
dfs(1, 0);
cout << ans << '\n';
return 0;
}

F

题解

知识点:计算几何。

纯纯的计算几何(没学过,函数都是现场造的,好难qwq。

注意到是从上往下看,因此考虑从下往上遍历,考虑每一个被上面盖住的弧长即可。

实现过程上,先考虑两个圆 \(a[i]\) 被 \(a[j]\) 覆盖,且是相交的情况。发现只需要用一个余弦定理计算以 \(a[j]\) 半径为对边,\(a[i]\) 与 \(Dist_{C_i,C_j}\) 为邻边的三角形的夹角弧度 \(\theta\),然后乘以二就是被覆盖的弧长弧度;如果两个圆相离或者后者包含于前者则弧度为 \(0\) ;如果前者包含于后者,是全覆盖,弧度为 \(2\pi\)。

但事实上不止一个圆覆盖,因此要考虑重复覆盖的问题,这涉及到了区间合并,因此考虑以 \(x\) 轴正半轴为基准,逆时针为正方向,形成区间 \([-\pi,\pi]\) ,同时刚好满足 atan2 函数的特性。

先计算 \(\overrightarrow {C_iC_j}\) 的区间弧度 \(base\),然后加减 \(\theta\) ,得到始边弧度和终边弧度。同时要考虑始边弧度 \(<-\pi\) 和终边弧度 \(>\pi\) 的特判,要把一个角拆成两个角,比如 \([-1.1\pi,0.5\pi]\) 拆成 \([0.9\pi,\pi]\) 与 \([-\pi,0.5\pi]\) 。

随后按起边从小到大排序合并区间,要注意有可能该圆不被任何圆覆盖,\(cnt\) 为 \(0\) ,因此不能以第一个弧段为初始条件,应该以 \([-\pi-1,-\pi-1]\) 类似的为初始条件,或者以\([\pi+1,\pi+1]\) 额外加入数组作为终止条件,顺便还可以把最后一段有效区间加上,我个人喜欢后面这种。

时间复杂度 \(O(n^2)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

const double pi = acos(-1.0);

struct Point {
double x;
double y;
}; struct Circle {
Point A;
double r;
}a[1007]; double sqr(double x) {
return x * x;
} double dist2(Point A, Point B) {
return sqr(A.x - B.x) + sqr(A.y - B.y);
} double rad(double a, double b, double c) {///余弦定理,a对边,b,c邻边
return acos((b * b + c * c - a * a) / (2 * b * c));
} double xrad(Point A, Point B) {///与x轴正方向夹角[-pi,pi]
return atan2(A.y - B.y, A.x - B.x);///斜率y/x,且由象限决定
} struct node {
double x;
double y;
}xy[1007 << 1]; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1;i <= n;i++)
cin >> a[i].A.x >> a[i].A.y >> a[i].r;
double ans = 0;
for (int i = 1;i <= n;i++) {
int cnt = 0;
for (int j = i + 1;j <= n;j++) {
++cnt;
double len2 = dist2(a[i].A, a[j].A);
if (len2 >= sqr(a[i].r + a[j].r) || sqrt(len2) <= a[i].r - a[j].r) {///相离 或 j内含于i
xy[cnt] = { 0,0 };
continue;
}
else if (sqrt(len2) <= a[j].r - a[i].r) {///i内含于j,全盖住了
xy[cnt] = { -pi,pi };
break;
}
double xita = rad(a[j].r, a[i].r, sqrt(len2));
double base = xrad(a[j].A, a[i].A);
xy[cnt].x = base - xita;
xy[cnt].y = base + xita;
if (xy[cnt].x < -pi) {///起边小于-pi那就分成[起边+2pi,pi],[-pi,终边]
cnt++;
xy[cnt] = { xy[cnt - 1].x + 2 * pi, pi };
xy[cnt - 1].x = -pi;
}
else if (xy[cnt].y > pi) {///同上
cnt++;
xy[cnt] = { -pi, xy[cnt - 1].y - 2 * pi };
xy[cnt - 1].y = pi;
}
}
sort(xy + 1, xy + cnt + 1, [&](node a, node b) {
return a.x < b.x;
});///按起边从小到大排序,开始合并区间
xy[++cnt] = { pi + 1,pi + 1 };///终止特殊判断,方便把最后一段有效段加上
ans += 2 * pi * a[i].r;///先加上周长
double lpre = -pi - 1, rmax = -pi - 1;///初始化负无穷,不能初始化第一个,因为有可能一个都没有(如果上面加了终止判断,可以不考虑这个)
for (int j = 1;j <= cnt;j++) {///合并区间
if (xy[j].x >= rmax) {
ans -= (rmax - lpre) * a[i].r;///减去一个区间的周长
lpre = xy[j].x;
}
rmax = max(rmax, xy[j].y);
}
}
cout << fixed << setprecision(15) << ans << '\n';
return 0;
}

G

题解

方法一

知识点:manachar。

不会qwq。

方法二

知识点:回文自动机。

模板题。不多说(因为也不会说qwq。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

方法一

方法二

#include<bits/stdc++.h>
#define ll long long
using namespace std; const int N = 5e5 + 10;
char s[N];
int n, lst, len[N];
int now, tot = 1, fail[N], cnt[N], t[N][26]; int getfail(int u, int p) {
while (p - len[u] - 1 <= 0 || s[p - len[u] - 1] != s[p]) u = fail[u];
return u;
} int insert(char c, int id) {
int p = getfail(now, id);
if (!t[p][c - 'a']) {
fail[++tot] = t[getfail(fail[p], id)][c - 'a'];
t[p][c - 'a'] = tot;
len[tot] = len[p] + 2;
cnt[tot] = cnt[fail[tot]] + 1;
}
return cnt[now = t[p][c - 'a']];
} ll ans[3]; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
cin >> s + 1;
fail[0] = 1, len[1] = -1;
for (int i = 1;i <= n;i++) {
lst = insert(s[i], i);
if (s[i] == 'k') ans[0] += lst;
else if (s[i] == 'f') ans[1] += lst;
else if (s[i] == 'c') ans[2] += lst;
}
cout << ans[0] << ' ' << ans[1] << ' ' << ans[2] << '\n';
return 0;
}

H

题解

知识点:数学,计算几何。

画图,求并集面积。

显然,\(S_U = 2(\dfrac{n}{2})^2 + \dfrac{1}{2}\pi(\dfrac{n}{2})^2 = \dfrac{n^2}{2} + \dfrac{\pi n^2}{8}\) 。

(把union area看成交集QAQ,要被英语退役了)

时间复杂度 \(O(1)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>

using namespace std;

int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
double n;
cin >> n;
cout << fixed << setprecision(15) << n * n / 2.0 + n * n * acos(-1.0) / 8.0 << '\n';///圆和多边形面积并集
return 0;
}

K

题解

知识点:数学。

首先如果 \(n-k<=k\) 则一定拿不到。

然后根据鸽巢原理。因为一对耳机有两个头,最坏情况是每对都只拿了一个头即 \(n-k\) 个耳机,还要补上 \(k+1\) 个耳机凑成 \(k+1\) 对,因此一共要拿 \(n+1\) 个耳机。

时间复杂度 \(O(1)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>

using namespace std;

int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, k;
cin >> n >> k;
if (n - k <= k) {
cout << -1 << '\n';
return 0;
}
cout << n + 1 << '\n';
return 0;
}

蔚来杯2022牛客暑期多校训练营5 ABCDFGHK的更多相关文章

  1. 蔚来杯2022牛客暑期多校训练营6 ABGJM

    比赛链接 A 题解 知识点:数学,构造. 题目要求构造一个长为 \(m\) 的序列 \(c\) ,\(m\) 自选,使得 \(c\) 的无限循环序列 \(b\) 中任意连续 \(a_i\) 个数中都存 ...

  2. 蔚来杯2022牛客暑期多校训练营7 CFGJ

    比赛链接 C 题解 方法一 知识点:思维. 先统计没有出现的数,每个都可以随便放,所以作为补位用的. 将原数组左移一位作为预定的答案数组,然后开始检查.如果和原数组一样,则用补位数字填充,如果不一样就 ...

  3. "蔚来杯"2022牛客暑期多校训练营9 G Magic Spells【马拉车+哈希】

    四川今天又上热搜了,继南部疫情的未雨绸缪后,龙槽沟是真的倾盆大雨了.我没有兴趣虚伪矫情地对罹难的游人表达同情,因为人与人互不相通徒增谈资:我也没有兴趣居高临下地对擅闯的愚人表达不屑,因为你我皆为乌合之 ...

  4. 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题)

    layout: post title: 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题) author: "luowentaoaa" c ...

  5. 2021牛客暑期多校训练营3 J 思维

    传送门 J-Counting Triangles_2021牛客暑期多校训练营3 (nowcoder.com) 题目 Goodeat finds an undirected complete graph ...

  6. B-xor_2019牛客暑期多校训练营(第四场)

    题意 给出n个数组(每组数个数不定),m个询问 l, r, x 序号在区间\([l,r]\)的每个数组是否都可以取出任意个数异或出x 题解 判断一个数组能否异或出x,是简单的线性基问题 判断多个线性基 ...

  7. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  8. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  9. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

随机推荐

  1. 832. Flipping an Image - LeetCode

    Question 832. Flipping an Image Solution 题目大意:将1列与最后n列对换,2列与n-1列对换-然后再将每个元素取反 思路:遍历二维数组的左半边,对每个元素先做对 ...

  2. 29. Divide Two Integers - LeetCode

    Question 29. Divide Two Integers Solution 题目大意:给定两个数字,求出它们的商,要求不能使用乘法.除法以及求余操作. 思路:说下用移位实现的方法 7/3=2, ...

  3. 解决windows server 2008r2服务器自动关机

    问题 具体表现就是系统自动关机,网上说是开机后2小时就会自动关机 系统版本: 解决 PsTools下载 解压:PSTools.zipg,如解压到C:\PSTools目录下 执行如下命令,打开注册表 W ...

  4. unity---公共模块MonoController

    公共模块 如果有很多类使用Update()函数,会导致性能浪费 如果函数统一在一个Update()中执行 代码 上述,需要将脚本挂载到物体上, 故新建了一个管理类MonoMgr Mgr另外的作用 可以 ...

  5. P4169 [Violet]天使玩偶

    两种操作:1.加入点(x,y); 2.查询距(x,y)最近的点的曼哈顿距离距离 思路:绝对值拆开通常可以取max,不过这里直接分类讨论4种情况,我们发现如果找\(i\)点左下点\(j\)\((x_j& ...

  6. Python 微博搜索爬虫

    微博搜索爬虫 网页分析 由于网页端反爬虫机制比较完善所以才去移动端进行爬虫. url地址:https://m.weibo.cn/ 搜索框,输入关键词进行搜索 对网页进行抓包,找到相关数据 查看数据是否 ...

  7. Python数据分析--Numpy常用函数介绍(6)--Numpy中矩阵和通用函数

    在NumPy中,矩阵是 ndarray 的子类,与数学概念中的矩阵一样,NumPy中的矩阵也是二维的,可以使用 mat . matrix 以及 bmat 函数来创建矩阵. 一.创建矩阵 mat 函数创 ...

  8. CabloyJS 4.12震撼发布,及新版教程尝鲜

    引言 凡是可以用 JavaScript 来写的应用,最终都会用 JavaScript 来写 | Atwood 定律 目前市面上出现的大多数与 NodeJS 相关的框架,基本都将 NodeJS 定位在工 ...

  9. Arduino WeMos D1 开发环境搭建

    更新记录 2022年4月16日:本文迁移自Panda666原博客,原发布时间:2021年9月2日. WeMos D1介绍 WeMos D1开发板全称是WeMos D1 WiFI UNO R3开发板,基 ...

  10. 论文解读(USIB)《Towards Explanation for Unsupervised Graph-Level Representation Learning》

    论文信息 论文标题:Towards Explanation for Unsupervised Graph-Level Representation Learning论文作者:Qinghua Zheng ...