【LOJ502】[LibreOJ β Round] ZQC 的截图 (随机化)
真的是神仙题目啊……
题目
我认为官方题解比我讲得好。
分析
这是一道蒙特卡洛算法的好题
上面那个奇奇怪怪的词是从官方题解里看到的,意思大概就是随机化算法 …… ?
一句话题意:给一棵有根树,每个点有一种颜色。每次加一个叶子,询问从根到这个叶子的路径上是不是所有颜色的出现次数都是 \(3\) 的倍数。如果不是,再询问是不是只有一个点不是 \(3\) 的倍数。如果只有一个点不是 \(3\) 的倍数,再询问这个点的编号。强制在线。
思考部分分似乎对想到正解没有什么帮助(谁能想到这题是随机化啊 wq ),所以直接来说正解。
考虑给每种颜色分配一个长为 \(w\) 的随机向量作为权值(我取\(w=40\) 。如果你像我一样没学过高中数学对向量不熟悉,就理解成一个长为 \(w\) 的数组好了)。把根到叶子路径上所有点的颜色的权值相加,每一维分别在模 \(3\) 意义下进行。如果和的每一维(可以理解成数组的每一个元素)都是 \(0\) ,那么说明所有颜色的出现次数都是 \(3\) 的倍数。这个算法的正确率证明如下:
在模域下,若干个随机的数加起来的结果是一个随机数(这里的「随机」指模域内每个数概率相等,下同);在模质数域下,随机数乘上一个非 \(0\) 整数仍然是随机数。而由于一堆随机数按特定顺序拼在一起就是一个随机向量,所以在模质数域下随机向量的加、数乘(乘数非 \(0\) )的结果仍然是随机向量。回到本题。如果不是所有颜色的出现次数都是 \(3\) 的倍数,那么和就相当于所有出现次数不是 \(3\) 的倍数的颜色的权值的 \(1\) 倍或 \(2\) 倍之和。由于 \(3\) 是质数,根据上述性质,和仍然是一个随机向量。这个随机向量是 \(\vec{0}\) 的概率是 \(\frac{1}{3^w}\) ,非常小。
如何判断是否只有一种颜色不是 \(3\) 的倍数呢?如果只有一种颜色不是 \(3\) 的倍数,那么和就是这种颜色的权值的 \(1\) 倍或 \(2\) 倍。那么直接判断一下是否存在一种颜色的权值是和的 \(1\) 倍或 \(2\) 倍(模 \(3\) 意义下乘 \(4\) 相当于乘 \(1\) )即可。用哈希表维护。
这样做的正确率如何呢?如果有不止一种颜色出现的次数不是 \(3\) 的倍数,和就是一个随机向量。和与一种颜色的权值的 \(1\) 倍或 \(2\) 倍相等的概率为 \(1-(1-\frac{2}{3^w})^{n}\) 。直观感受一下感觉挺小的(毕竟 \(3^{40}=12,157,665,459,056,928,801\) )
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cstdlib>
using namespace std;
namespace zyt
{
template<typename T>
inline bool read(T &x)
{
char c;
bool f = false;
x = 0;
do
c = getchar();
while (c != EOF && c != '-' && !isdigit(c));
if (c == EOF)
return false;
if (c == '-')
f = true, c = getchar();
do
x = x * 10 + c - '0', c = getchar();
while (isdigit(c));
if (f)
x = -x;
return true;
}
template<typename T>
inline void write(T x)
{
static char buf[20];
char *pos = buf;
if (x < 0)
putchar('-'), x = -x;
do
*pos++ = x % 10 + '0';
while (x /= 10);
while (pos > buf)
putchar(*--pos);
}
typedef unsigned long long ull;
const int N = 1e6 + 10, M = 2e6 + 10;
int lastans = 0, n, m;
struct bitset_3
{
const static int B = 32;
ull data;
bitset_3(const ull &b = 0)
: data(b) {}
void set(const int a, const int x)
{
data &= ~((1ULL << (a << 1)) | (1ULL << (a << 1 | 1)));
data |= (ull(x & 3) << (a << 1));
}
int query(const int a) const
{
return (data >> (a << 1)) & 3;
}
void rand()
{
for (int i = 0; i < B; i++)
set(i, std::rand() % 3);
}
bool operator == (const bitset_3 &b) const
{
return data == b.data;
}
bitset_3 operator ^ (const bitset_3 &b) const
{
bitset_3 ans;
for (int i = 0; i < B; i++)
ans.set(i, (query(i) + b.query(i)) % 3);
return ans;
}
ull to_ull() const
{
return data;
}
bool empty() const
{
return !data;
}
}w[N], v[M];
namespace Hash_Table
{
const int P = 999983;
struct edge
{
bitset_3 to;
int w, next;
}e[N];
int head[P], ecnt;
void init()
{
memset(head, -1, sizeof(head));
ecnt = 0;
}
void add(const int a, const bitset_3 &b, const int c)
{
e[ecnt] = (edge){b, c, head[a]}, head[a] = ecnt++;
}
void add(const bitset_3 &b, const int c)
{
add(b.to_ull() % P, b, c);
}
int query(const bitset_3 &b)
{
for (int i = head[b.to_ull() % P]; ~i; i = e[i].next)
if (e[i].to == b)
return e[i].w;
return -1;
}
}
int work()
{
Hash_Table::init();
srand(30624700);
read(n), read(m);
for (int i = 1; i <= n; i++)
{
w[i].rand();
Hash_Table::add(w[i], i);
}
for (int i = 1; i <= m; i++)
{
int u, fa, tmp;
read(u), read(fa);
u ^= lastans, fa ^= lastans;
v[i] = (v[fa] ^ w[u]);
if (v[i].empty())
write(lastans = -1);
else if (~(tmp = Hash_Table::query(v[i])))
write(lastans = tmp);
else if (~(tmp = Hash_Table::query(v[i] ^ v[i])))
write(lastans = tmp);
else
write(lastans = -2);
putchar('\n');
}
return 0;
}
}
int main()
{
return zyt::work();
}
【LOJ502】[LibreOJ β Round] ZQC 的截图 (随机化)的更多相关文章
- LibreOJ β Round #2 题解
LibreOJ β Round #2 题解 模拟只会猜题意 题目: 给定一个长为 \(n\) 的序列,有 \(m\) 次询问,每次问所有长度大于 \(x\) 的区间的元素和的最大值. \(1 \leq ...
- loj #547. 「LibreOJ β Round #7」匹配字符串
#547. 「LibreOJ β Round #7」匹配字符串 题目描述 对于一个 01 串(即由字符 0 和 1 组成的字符串)sss,我们称 sss 合法,当且仅当串 sss 的任意一个长度为 ...
- [LOJ#531]「LibreOJ β Round #5」游戏
[LOJ#531]「LibreOJ β Round #5」游戏 试题描述 LCR 三分钟就解决了问题,她自信地输入了结果-- > -- 正在检查程序 -- > -- 检查通过,正在评估智商 ...
- [LOJ#530]「LibreOJ β Round #5」最小倍数
[LOJ#530]「LibreOJ β Round #5」最小倍数 试题描述 第二天,LCR 终于启动了备份存储器,准备上传数据时,却没有找到熟悉的文件资源,取而代之的是而屏幕上显示的一段话: 您的文 ...
- [LOJ#516]「LibreOJ β Round #2」DP 一般看规律
[LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...
- [LOJ#515]「LibreOJ β Round #2」贪心只能过样例
[LOJ#515]「LibreOJ β Round #2」贪心只能过样例 试题描述 一共有 \(n\) 个数,第 \(i\) 个数 \(x_i\) 可以取 \([a_i , b_i]\) 中任意值. ...
- [LOJ#525]「LibreOJ β Round #4」多项式
[LOJ#525]「LibreOJ β Round #4」多项式 试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k−1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) ...
- [LOJ#526]「LibreOJ β Round #4」子集
[LOJ#526]「LibreOJ β Round #4」子集 试题描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两 ...
- [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机)
[LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机) 试题描述 IOI 的比赛开始了.Jsp 和 Rlc 坐在一个角落,这时他们听到了一个异样的声音 …… 接着他们发现自己收 ...
随机推荐
- 数据库join解释 与视图
数据库的视图是表运算的结果. 数据库的表是数据单元: join是运算符: 视图是运算结果. 数据库join解释 1.join:将两个表结构连接成一个视图 2.left.right.inner: 从基准 ...
- Struct Socket详细分析(转)
原文地址:http://anders0913.iteye.com/blog/411986 用户使用socket系统调用编写应用程序时,通过一个数字来表示一个socket,所有的操作都在该数字上进行,这 ...
- pom.xml中使用“import”的scope来解决Maven项目单继承问题
测试环境 maven 3.3.9 想必大家在做SpringBoot应用的时候,都会有如下代码: <parent> <groupId>org.springframework.bo ...
- dotnet core linux 接入支付宝H5支付,提示:System.PlatformNotSupportedException","Message":"'CspParameters' requires Windows Cryptographic API (CAPI), which is not available on this platform.
用的官方提供的demo,实际上部署后却出现了上图的错误.和技术支持沟通无效后,走上了不归路. 在微软的github dotnet/core开源库提交了issue后,终于获得了解决.附上链接:https ...
- pytcharm无法debug:pydev debugger: process 15188 is connecting
今天问老师,老师说需要设置断点,果然设置断点后就可以正常调试了.
- ent 基本使用八 索引
我们可以在ent 的schema 中定义index 可以方便的控制数据约束,使用索引可以加速我们的访问以及数据的唯一性处理 配置字段索引 多字段索引 package schema import ( ...
- 【CSGRound2】逐梦者的初心(洛谷11月月赛 II & CSG Round 2 T3)
题目描述# 给你一个长度为\(n\)的字符串\(S\). 有\(m\)个操作,保证\(m≤n\). 你还有一个字符串\(T\),刚开始为空. 共有两种操作. 第一种操作: 在字符串\(T\)的末尾加上 ...
- Shell 逐行读取文件的4中方法
方法1:while循环中执行效率最高,最常用的方法. function while_read_LINE_bottm(){ While read LINE do echo $LINE done < ...
- 二分法递归版本(c++)
利用二分法求解在区间[0,π/2]上的根 #include<iostream> #include <cmath> using namespace std; double dic ...
- Linux中git用https连接时不用每次输入密码
应用场景: 比如每天凌晨执行crontab对应的项目部署脚本(使用git作为项目的版本控制). 如果不这样做会怎么样? 每次部署都要git clone并输入对应的用户名和密码,需要人工.这样就显得很不 ...