题面: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. 谁动了我的主机? 之活用History命令

    点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! Linux系统下可通过history命令查看用户所有的历 ...

  2. 一个登录点两个逻辑漏洞-edusrc

    最近呢, 也是基础漏洞学的差不多了, 就在edusrc上面实战, 刚开始搞一些信息泄漏啥的, 提交了十几个, 结果就他娘的通过了一个. 咱也就不碰信息泄漏了, 没得意思. 关于这个学校测试时也是有坑的 ...

  3. docker 保存,加载,导入,导出 命令

    持久化docker的镜像或容器的方法 docker的镜像和容器可以有两种方式来导出 docker save #ID or #Name docker export #ID or #Name docker ...

  4. 804. Unique Morse Code Words - LeetCode

    Question 804. Unique Morse Code Words [".-","-...","-.-.","-..&qu ...

  5. Python数据分析--Numpy常用函数介绍(2)

    摘要:本篇我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy的基本数学和统计分析函数.学习读写文件的方法,并尝试函数式编程和NumPy线性代数运算,来学习NumPy的常用函数. ...

  6. Fail2ban 配置详解 配置说明

    fail2ban的配置主要由基础配置(fail2ban.conf)和监禁配置(jail.conf)两部分组成. fail2ban的配置采用标签块"[块名]"和键值"key ...

  7. 我熬夜读完这份“高分宝典”,竟4面拿下字节跳动offer

    前言 怎样的契机? 实际上,目前毕业已经两年时间了,在大学时就已经开始关注字节跳动的发展.一开始,我是电气自动化专业的,大二清楚目标之后就转计算机了,大四进了一家小型的互联网公司实习,具体就不说哪家了 ...

  8. node.js环境安装及环境变量

    1.nodejs官网下载对应系统的安装包 2.除了你想自定义安装的路径其他一切一直点next往下走 3.打开cmd命令窗口输入node -v,看到v.xx.xx代表node已经装好 node -v 4 ...

  9. SpringBoot之:SpringBoot中使用HATEOAS

    目录 简介 我们的目标 构建Entity和Repository 构建HATEOAS相关的RepresentationModel 构建Controller HATEOAS的意义 总结 简介 HATEOA ...

  10. SAP Html viewer

    1 *&---------------------------------------------------------------------* 2 *& Report RSDEM ...