比赛链接

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. ArcGIS和ArcEngine导出地图时,png格式支持背景透明

    1.ArcGIS支持导出PNG,背景透明 导出png时,背景色和透明色不能设置为空,必须设置为同一个颜色,通常使用白色. 2.ArcEngine支持导出PNG,背景透明 //1.创建export IE ...

  2. 好客租房48-组件的props(基本使用)

    组件是封闭的 要接受外部数据应该通过props来实现 props的作用:接受传递给组件的数据 传递数据:给组件标签添加属性 接收数据:函数组件通过参数props接收数据 类组件通过this.props ...

  3. 大数据分析——sklearn模块安装

    前提条件:numpy.scipy以及matplotlib库的安装 (注:所有操作都在pycharm命令终端进行) ①numpy安装 pip install numpy ②scipy安装 pip ins ...

  4. 08shell脚本

    shell脚本编程 1.1简介 什么是shell脚本 shell脚本: 就是一些命令的集合, 在脚本文件中可以有流程控制, 如顺序, 条件分支和循环等 脚本文件一般一.sh文件为扩展名, 但是不是必须 ...

  5. Vue 基础篇---computed 和 watch

    最近在看前端 Vue方面的基础知识,虽然前段时间也做了一些vue方面的小项目,但总觉得对vue掌握的不够 所以对vue基础知识需要注意的地方重新撸一遍,可能比较零碎,看到那块就写哪块吧 1.vue中的 ...

  6. ML第4周学习小结

    本周收获 总结一下本周学习内容: 1.学习了<深入浅出Pandas>的第五章:Pandas高级操作的两个内容 添加修改数据 高级过滤 我的博客链接: Pandas:添加修改.高级过滤 2. ...

  7. 贝塞尔曲线在Unity中的应用

    前言:国庆放假后基本整个人的散掉了.加之种种原因,没时间没心情写博客.最近研究了一下3d的一些效果.其中有类似翻书撕纸的操作,可是一个panel怎么由平整的变成弯曲的呢? 两点可以确定一条直线,三点可 ...

  8. 「洛谷 P3834」「模板」可持久化线段树 题解报告

    题目描述 给定n个整数构成的序列,将对于指定的闭区间查询其区间内的第k小值. 输入输出格式 输入格式 第一行包含两个正整数n,m,分别表示序列的长度和查询的个数. 第二行包含n个整数,表示这个序列各项 ...

  9. 前端2CSS2

    内容概要 伪元素选择器 选择器优先级 字体样式 文字属性 背景属性 display属性 边框属性 盒子模型 浮动(重要) 解决浮动造成的影响 内容详情 伪元素选择器 """ ...

  10. 轻量级多级菜单控制框架程序(C语言)

    1.前言 作为嵌入式软件开发,可能经常会使用命令行或者显示屏等设备实现人机交互的功能,功能中通常情况都包含 UI 菜单设计:很多开发人员都会有自己的菜单框架模块,防止重复造轮子,网上有很多这种菜单框架 ...