多校B层冲刺NOIP20211111模拟12
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的更多相关文章
- 【CJOJ P1957】【NOIP2010冲刺十模拟赛】数字积木
[NOIP2010冲刺十模拟赛]数字积木 Description 小明有一款新式积木,每个积木上都有一个数,一天小明突发奇想,要是把所有的积木排成一排,所形成的数目最大是多少呢? 你的任务就是读入n个 ...
- noip模拟12[简单的区间·简单的玄学·简单的填数]
noip模拟12 solutions 这次考试靠的还是比较好的,但是还是有不好的地方, 为啥嘞??因为我觉得我排列组合好像白学了诶,文化课都忘记了 正难则反!!!!!!!! 害没关系啦,一共拿到了\( ...
- 冲刺Noip2017模拟赛7 解题报告——五十岚芒果酱
1.二叉树(binary) .二叉树 (binary.cpp/c/pas) [问题描述] 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: ()若左子树不空,则左子树上所有结点的值均小于它的根结 ...
- Noip模拟12 2021.7.12
T1 interval 亏得昨天晚上改掉了T3并且理解了单调栈,今天一扫这题目就知道要用啥了. 先预处理出以a[i]为最大值的最大左右区间.然后再将a[i]取%!!!是的,要不然会影响单调栈的使用.. ...
- Beta版本冲刺第一天 12.5
一.站立式会议照片: 二.项目燃尽图: 三.项目进展: 成 员 前段时间完成任务 今天完成任务 明天要做任务 问题困难 心得体会 胡泽善 对Alpha版本的分析总结,学习新技术,对Beta版本的讨论规 ...
- Beta版本冲刺第二天 12.6
一.站立式会议照片: 二.项目燃尽图: 三.项目进展: 成 员 昨天完成任务 今天完成任务 第三天冲刺要做任务 问题困难 心得体会 胡泽善 完成了"记住密码"的的逻辑以及BUG修改 ...
- layer层、modal模拟窗 单独测试页面
layer_test.jsp <%@ page language="java" import="java.util.*" pageEncoding=&qu ...
- 【Alpha 冲刺】 1/12
1. 任务明细及任务量 Alpha版本任务安排(非固化版本,视情况调整,若有遗漏,及时补充) 职务 姓名 预期负责的模块页面 模块页面/任务明细 难度系数(0~1)(根据UI/功能实现难度划分) 预计 ...
- HDU 5373(2015多校7)-The shortest problem(模拟%11)
题目地址:pid=5373">HDU 5373 题意:给你一个数n和操作次数t,每次操作将n的各位数之和求出来放在n的末尾形成新的n,问t次操作后得到的n能否够被11整除. 思路:就是 ...
- NOIP模拟12
也算是最近几次比较水的一次吧. 考试时看T1像个打表找规律的题,扔了,去看T2,带修莫队??不会,完戏.看了T3,我决定还是去看T1. 看着T1,我突然发现T2是个大水题:主席树就行,不带修,修改时只 ...
随机推荐
- Element中使用el-select选中后不显示值
<el-select v-model="form.data" placeholder="选择参数" @change="changeThis&qu ...
- DDoS攻击--Syn_Flood攻击防护详解(TCP)
https://blog.csdn.net/qq_34777600/article/details/81946514
- 斯坦福NLP课程 | 第11讲 - NLP中的卷积神经网络
作者:韩信子@ShowMeAI,路遥@ShowMeAI,奇异果@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/36 本文地址:http://www. ...
- 905. Sort Array By Parity - LeetCode
Question 905. Sort Array By Parity Solution 题目大意:数组排序,偶数放前,奇数在后,偶数的数之间不用管顺序,奇数的数之间也不用管顺序 思路:建两个list, ...
- RabbitMQ 环境安装
每日一句 Wisdom is knowing what to do next, skill is knowing how to do it, and virtue is doing it. 智慧是知道 ...
- python 的 @staticmethod和@classmethod和普通实例方法
参考:https://www.huaweicloud.com/articles/12607084.html https://blog.csdn.net/qq_30708445/article/deta ...
- vue大型电商项目尚品汇(后台篇)day04
昨天太晚就没来得及更新,今天是spu管理界面,这个界面一共有三个界面需要切换,完成了两个界面,而且今天的难度在于最后两个章节,富有一定的逻辑性,当然中间也有很多需要注意的,比如ElementUI的照片 ...
- 1.2 操作系统的第二个功能——并发功能 -《zobolの操作系统学习札记》
1.2 操作系统的第二个功能--并发功能 目录 1.2 操作系统的第二个功能--并发功能 问1:什么是并发功能?并发功能是必要的吗? 问2:并发功能必须要求拥有多核CPU吗? 问3:多核CPU和单核C ...
- 关于个人项目(臻美MV【仿抖音App】)滑动切换视频的分析(前端角度)
我们知道你天天刷抖音的时候可以上滑切换视频,互不影响.那么我们站在前端的角度能否可以实现这种效果呢?这是我的个人项目:臻美MV 下面我是用Vue写的,现在我把它开源. Vue: 初始界面 <te ...
- easyui combobox重复渲染问题
当一个页面有两个easyui combobox存在时,并且同时给两个combobox赋相同值,某些easyui的版本会导致其中一个无法切换选项. 解决办法,分两步赋值,可解决问题