题面:PDFhttp://xn--gwt928b.accoders.com/pdf/10248/10248.pdfhttp://xn--gwt928b.accoders.com/pdf/10248/10248.pdf

A

给定一棵 n 个点的有根树,节点编号为 1~n,根节点为 1。你会不停地重复 以下操作,直到所有点被覆盖为止:等概率随机树上的一个未被覆盖的点,并 覆盖这个点到根路径上的所有点。请问你的期望操作次数是多少?为了避免高 精度运算,你只需要输出答案对 998244353 取模后的结果。

概率期望经典入门题,根据期望的线性性,答案就是每个点被选到的期望之和,每个点的贡献为一,所以只需要求每个点被选到的概率即可,每个点必须在它的子树中的点被选之前选,所以概率是

#include <iostream>
#include <cstdio>
#include <cstring> using namespace std; const int MOD = 998244353;
const int N = 10000000; int n, head[N + 50], num, inv[N + 50], siz[N + 50], f[N + 50]; void Read(int &x)
{
x = 0; int p = 0; char st = getchar();
while (st < '0' || st > '9') p = (st == '-'), st = getchar();
while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
x = p ? -x : x;
return;
} struct Node
{
int next, to;
} edge[N * 2 + 50]; void Addedge(int u, int v)
{
edge[++num] = (Node){head[u], v};
head[u] = num;
return;
} int main()
{
Read(n);
inv[1] = 1;
for (int i = 2; i <= n; i++) Read(f[i]), inv[i] = 1LL * (MOD - MOD / i) * inv[MOD % i] % MOD;
for (int i = n; i >= 1; i--) siz[i]++, siz[f[i]] += siz[i];
int ans = 0;
for (int i = 1; i <= n; i++) (ans += inv[siz[i]]) %= MOD;
printf("%d", ans);
return 0;
}

B

有 n 颗糖果,编号为 1~n,每颗糖果有美味度  和美观度 。请你从中取 出不超过  颗糖果,使得这些糖果的美味度之和大于所有糖果美味度总和 的一半,且美观度之和大于所有糖果美观度总和的一半,或判断无解。

这道题的数学题我做过!那道题里它说有199个a,199个b!类似,对于偶数,随便取出来一个使得剩下的变成奇数个。

对于奇数,按a排序,先取a最大的一个,然后剩下的从前往后两两分为一组,每组选b较大的一个。

这样一定是正确的因为每组b都选了较大的,最劣情况下选的和没选的相同,但是另外还选了一个元素,所以b的总和一定大于所有的b的一半;因为是按照a排序两两一组,最劣情况下每组都选了较小的a,但是因为我们已经选了最大的a,就相当于可以给元素重新分组,从后往前两两一组,这样就可以和b一样证明。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int N = 100000; int n; struct Node
{
int x, y, id;
} a[N + 50]; int Cmp(Node a, Node b)
{
return a.x < b.x;
} void Read(int &x)
{
x = 0; int p = 0; char st = getchar();
while (st < '0' || st > '9') p = (st == '-'), st = getchar();
while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
x = p ? -x : x;
return;
} int main()
{
Read(n);
for (int i = 1; i <= n; i++) Read(a[i].x), a[i].id = i;
for (int i = 1; i <= n; i++) Read(a[i].y);
printf("%d\n", n / 2 + 1);
sort(a + 1, a + n + 1, Cmp);
if (n % 2 == 0) printf("%d ", a[n].id), n--;
printf("%d ", a[n].id); n--;
for (int i = 1; i <= n - 1; i += 2) printf("%d ", a[i].y > a[i + 1].y ? a[i].id : a[i + 1].id);
return 0;
}

C

给定一棵 n 个点的有根树,节点编号为 1~n,根节点为 1。最开始所有点都 是白色,你需要选择一些点染成黑色,同时有若干条限制,限制有两种:

A 类限制:x 的子树内至少有 y 个点被染成黑色

B 类限制:x 的子树外至少有 y 个点被染成黑色 请问最少把多少个点染成黑色才能满足条件,如果无解输出-1。

第一种限制可以求出每个点子树内染色的下限,第二种限制通过二分可以求出每个点子树内染色的上限,二分判定即可。

#include <iostream>
#include <cstdio>
#include <cstring> using namespace std; const int N = 100000;
const int INF = 0x7fffffff; int n, head[N + 50], num, siz[N + 50], minn[N + 50], maxx[N + 50], mid, flag, xx[N + 50][2], mm[N + 50]; struct Node
{
int next, to;
} edge[N * 2 + 50]; void Addedge(int u, int v)
{
edge[++num] = (Node){head[u], v};
head[u] = num;
return;
} void Read(int &x)
{
x = 0; int p = 0; char st = getchar();
while (st < '0' || st > '9') p = (st == '-'), st = getchar();
while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
x = p ? -x : x;
return;
} void Dfs(int x, int fa)
{
siz[x] = 1;
for (int i = head[x]; i; i = edge[i].next)
{
int v = edge[i].to;
if (v == fa) continue;
Dfs(v, x);
siz[x] += siz[v];
}
return;
} void Dfspd(int x, int fa)
{
mm[x] = mid - xx[x][1];
int tmp = 1;
for (int i = head[x]; i; i = edge[i].next)
{
int v = edge[i].to;
if (v == fa) continue;
Dfspd(v, x); tmp += mm[v];
}
mm[x] = min(mm[x], tmp);
if (mm[x] < xx[x][0]) flag = 0;
return;
} void Dfs2(int x, int fa)
{
int tmp = 0;
for (int i = head[x]; i; i = edge[i].next)
{
int v = edge[i].to;
if (v == fa) continue;
Dfs2(v, x);
tmp += xx[v][0];
}
xx[x][0] = max(tmp, xx[x][0]);
return;
} int main()
{
Read(n);
for (int i = 1, u, v; i <= n - 1; i++)
{
Read(u); Read(v);
Addedge(u, v); Addedge(v, u);
}
int a, b;
Dfs(1, 0);
Read(a);
for (int i = 1; i <= a; i++)
{
int x, y;
Read(x); Read(y);
xx[x][0] = max(xx[x][0], y);
if (y > siz[x]) { puts("-1"); return 0; }
}
Read(b);
for (int i = 1; i <= b; i++)
{
int x, y;
Read(x); Read(y);
xx[x][1] = max(xx[x][1], y);
if (y > n - siz[x]) { puts("-1"); return 0; }
}
Dfs2(1, 0);
int l = 0, r = n + 50;
while (l < r)
{
mid = (l + r) >> 1;
flag = 1;
Dfspd(1, 0);
if (flag) r = mid;
else l = mid + 1;
}
printf("%d\n", l);
return 0;
}

D

给定一棵 n 个点的有根树,节点编号为 1~n,根节点为 1,满足每个点的儿 子个数为 0 或 2 个。Alice 和 Bob 在这棵树上玩游戏,Alice 控制了所有到根距离 为偶数的非叶节点,Bob 控制了所有到根距离为奇数的非叶节点(距离就是两 点间的边数)。 游戏开始时,每个叶子节点 u 都会被分配一个二元组(c(u),d(u)),c 和 d 均为 [1,k]中的正整数。接下来 Alice 和 Bob 会分别对他们控制的每一个节点指定一个 重儿子,显然从根节点顺着重链会走到唯一一个叶结点 x,这时 Alice 的得分为 c(x),Bob 的得分为 d(x)。称两人的一种选择方案为一种策略,设叶子结点有 l 个,显然策略有种。 定义一种策略是均衡的,当且仅当 Alice 不改变方案时,Bob 无论怎么改变 自己的方案都无法使自己的得分变大;且 Bob 不改变方案时,Alice 无论怎么改 变自己的方案也无法使自己的得分变大。请问对于所有合法的初始叶结点权 值,均衡的策略的个数总和是多少?答案对 998244353 取模。

先转移出来可以随便修改决策时,两个人分别拿到最多i分的方案数。

然后注意到如果钦定一条重链,两个人的决策其实是独立的,所以再根据上面的东西转移出来走到x点时,每个人最后得分为i的决策数,在叶子节点相乘即可。

#include <iostream>
#include <cstdio>
#include <cstring> using namespace std; const int N = 5000;
const int MOD = 998244353; int n, k, g1[N + 50][N + 50], g2[N + 50][N + 50], bin[N + 50], ans, f1[N + 50][N + 50], f2[N + 50][N + 50]; struct Node
{
int son[2];
} tr[N + 50]; void Addedge(int u, int v)
{
if (!tr[u].son[0]) tr[u].son[0] = v;
else tr[u].son[1] = v;
return;
} void Read(int &x)
{
x = 0; int p = 0; char st = getchar();
while (st < '0' || st > '9') p = (st == '-'), st = getchar();
while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
x = p ? -x : x;
return;
} void Dfs1(int x, int y)
{
if (!tr[x].son[0])
{
for (int i = 1; i <= k; i++) g1[x][i] = g2[x][i] = i * k;//显然小于等于i的得分下该部分可以有i种选择,另外一部分随便选择。
bin[x] = k * k;
return;
}
Dfs1(tr[x].son[0], y ^ 1); Dfs1(tr[x].son[1], y ^ 1);//记录当前节点由谁控制。
int s0 = tr[x].son[0], s1 = tr[x].son[1];
bin[x] = 1LL * bin[s0] * bin[s1] % MOD * 2 % MOD;
if (y)
{
for (int i = 1; i <= k; i++)
g2[x][i] = 1LL * g2[s0][i] * g2[s1][i] % MOD * 2 % MOD, //乘2是因为要从两个儿子中选择一个当作重儿子,两个都得小于等于i是因为决策点可以任意改变。
g1[x][i] = (0LL + 1LL * g1[s0][i] * bin[s1] % MOD + 1LL * g1[s1][i] * bin[s0] % MOD) % MOD; //另外一个只能被钦定是走右边还是走左边,除了钦定的以外的另外一边因为觉决策点不会改变所以可以随便走。
}
else
{
for (int i = 1; i <= k; i++)
g1[x][i] = 1LL * g1[s0][i] * g1[s1][i] % MOD * 2 % MOD,
g2[x][i] = (0LL + 1LL * g2[s0][i] * bin[s1] % MOD + 1LL * g2[s1][i] * bin[s0] % MOD) % MOD;
}
return;
} void Dfs2(int x, int y)
{
if (!tr[x].son[0])
{
int tmp1 = 0, tmp2 = 0;
for (int i = 1; i <= k; i++) tmp1 = (0LL + tmp1 + f1[x][i]) % MOD, tmp2 = (0LL + tmp2 + f2[x][i]) % MOD;
ans = (0LL + ans + 1LL * tmp1 * tmp2 % MOD) % MOD;
return;
}
int s0 = tr[x].son[0], s1 = tr[x].son[1];
if (y)
{
for (int i = 1; i <= k; i++)
f2[s0][i] = 1LL * f2[x][i] * g2[s1][i] % MOD, f2[s1][i] = 1LL * f2[x][i] * g2[s0][i] % MOD,//可以执行决策的另外一边随便选。
f1[s0][i] = f1[x][i], f1[s1][i] = f1[x][i];//因为这里是独立的,所以不能执行决策就直接赋值。
}
else
{
for (int i = 1; i <= k; i++)
f1[s0][i] = 1LL * f1[x][i] * g1[s1][i] % MOD, f1[s1][i] = 1LL * f1[x][i] * g1[s0][i] % MOD,
f2[s0][i] = f2[x][i], f2[s1][i] = f2[x][i];
}
Dfs2(tr[x].son[0], y ^ 1); Dfs2(tr[x].son[1], y ^ 1);
return;
} int main()
{
Read(n); Read(k);
for (int i = 2, fa; i <= n; i++) Read(fa), Addedge(fa, i);
Dfs1(1, 0);
for (int i = 1; i <= k; i++) f1[1][i] = f2[1][i] = 1;//这里两个人的决策是独立的。
Dfs2(1, 0);
printf("%d", ans);
return 0;
}

记得点赞加关注哦!

多校B层冲刺NOIP20211111模拟12的更多相关文章

  1. 【CJOJ P1957】【NOIP2010冲刺十模拟赛】数字积木

    [NOIP2010冲刺十模拟赛]数字积木 Description 小明有一款新式积木,每个积木上都有一个数,一天小明突发奇想,要是把所有的积木排成一排,所形成的数目最大是多少呢? 你的任务就是读入n个 ...

  2. noip模拟12[简单的区间·简单的玄学·简单的填数]

    noip模拟12 solutions 这次考试靠的还是比较好的,但是还是有不好的地方, 为啥嘞??因为我觉得我排列组合好像白学了诶,文化课都忘记了 正难则反!!!!!!!! 害没关系啦,一共拿到了\( ...

  3. 冲刺Noip2017模拟赛7 解题报告——五十岚芒果酱

    1.二叉树(binary) .二叉树 (binary.cpp/c/pas) [问题描述] 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: ()若左子树不空,则左子树上所有结点的值均小于它的根结 ...

  4. Noip模拟12 2021.7.12

    T1 interval 亏得昨天晚上改掉了T3并且理解了单调栈,今天一扫这题目就知道要用啥了. 先预处理出以a[i]为最大值的最大左右区间.然后再将a[i]取%!!!是的,要不然会影响单调栈的使用.. ...

  5. Beta版本冲刺第一天 12.5

    一.站立式会议照片: 二.项目燃尽图: 三.项目进展: 成 员 前段时间完成任务 今天完成任务 明天要做任务 问题困难 心得体会 胡泽善 对Alpha版本的分析总结,学习新技术,对Beta版本的讨论规 ...

  6. Beta版本冲刺第二天 12.6

    一.站立式会议照片: 二.项目燃尽图: 三.项目进展: 成 员 昨天完成任务 今天完成任务 第三天冲刺要做任务 问题困难 心得体会 胡泽善 完成了"记住密码"的的逻辑以及BUG修改 ...

  7. layer层、modal模拟窗 单独测试页面

    layer_test.jsp <%@ page language="java" import="java.util.*" pageEncoding=&qu ...

  8. 【Alpha 冲刺】 1/12

    1. 任务明细及任务量 Alpha版本任务安排(非固化版本,视情况调整,若有遗漏,及时补充) 职务 姓名 预期负责的模块页面 模块页面/任务明细 难度系数(0~1)(根据UI/功能实现难度划分) 预计 ...

  9. HDU 5373(2015多校7)-The shortest problem(模拟%11)

    题目地址:pid=5373">HDU 5373 题意:给你一个数n和操作次数t,每次操作将n的各位数之和求出来放在n的末尾形成新的n,问t次操作后得到的n能否够被11整除. 思路:就是 ...

  10. NOIP模拟12

    也算是最近几次比较水的一次吧. 考试时看T1像个打表找规律的题,扔了,去看T2,带修莫队??不会,完戏.看了T3,我决定还是去看T1. 看着T1,我突然发现T2是个大水题:主席树就行,不带修,修改时只 ...

随机推荐

  1. MySQL 高频面试题,都在这了

    点击上方"开源Linux",选择"设为星标"回复"学习"获取独家整理的学习资料! 前言 本文主要受众为开发人员,所以不涉及到MySQL的服务 ...

  2. content应用

  3. Java遇上SPL:架构优势和开发效率,一个不放过

    摘要:如果我们在Java中也提供有一套完整的结构化数据处理和计算类库,那这个问题就能得到解决:即享受到架构的优势,又不致于降低开发效率. 本文分享自华为云社区<Java结构化处理SPL>, ...

  4. 使用NE555实现的延时开关电路

    NE555 的工作机制 先了解 NE555 的 Trigger(Pin2) 和 Threshold(Pin6) 如何检测电压并控制输出 如果 Trigger(Pin2) 检测到任何低于电源电压1/3的 ...

  5. Element中Tree树结构组件中实现Ctrl和Shift多选

    在Element中的树结构中, 实现多选功能,首先的是判断有没有按下键盘ctrl和shift按键.但是在Element中的tree组件的左键点击事件是没有提供$event鼠标属性判断的.所以就需要在函 ...

  6. Java高并发-概念

    一.为什么需要并行 业务要求 http处理多个客户端请求 java虚拟机启动多个线程 进程开销比线程大的多 性能 多线程在多核系统比单线程要好的多 摩尔定律失效 二.几个重要概念 2.1 同步和异步 ...

  7. 数据库与MySQL的下载使用

    目录 数据存储演变史 数据库应用发展史 数据库本质 数据库分类 关系型数据库 非关系型数据库 SQL与NoSQL MySQL简介 版本问题 下载使用 目录结构 基本使用 简单使用 系统服务 修改密码 ...

  8. 《Effective C++》阅读总结(三):资源管理

    C++中的资源管理非常重要,在将资源加载到内存后,便可以使用资源了,当我们不再需要资源时,我们要保证其正确的释放,才能将其占用的内存空间归还给操作系统,不正确的释放很容易造成内存泄漏.本章以资源管理类 ...

  9. 用树莓派USB摄像头做个监控

    [前言] 看着阴暗的角落里吃灰噎到嗓子眼的树莓派,一起陪伴的时光历历在目,往事逐渐涌上心头,每每触及此处,内心总会升腾起阵阵怜悯之情... 我这有两个设备,一个是积灰已久的树莓派,另一个是积灰已久的U ...

  10. Date类的常见用法——JavaSE基础

    Date类的常见用法 Date类属于java.util包 因此需要导入Date类 Date() 分配一个Date对象,并初始化此对象为系统当前的日期和时间,可以精确到毫秒). Date(long da ...