真的是神仙题目啊……

题目

LOJ502

官方题解

我认为官方题解比我讲得好。

分析

这是一道蒙特卡洛算法的好题

上面那个奇奇怪怪的词是从官方题解里看到的,意思大概就是随机化算法 …… ?

一句话题意:给一棵有根树,每个点有一种颜色。每次加一个叶子,询问从根到这个叶子的路径上是不是所有颜色的出现次数都是 \(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 的截图 (随机化)的更多相关文章

  1. LibreOJ β Round #2 题解

    LibreOJ β Round #2 题解 模拟只会猜题意 题目: 给定一个长为 \(n\) 的序列,有 \(m\) 次询问,每次问所有长度大于 \(x\) 的区间的元素和的最大值. \(1 \leq ...

  2. loj #547. 「LibreOJ β Round #7」匹配字符串

    #547. 「LibreOJ β Round #7」匹配字符串   题目描述 对于一个 01 串(即由字符 0 和 1 组成的字符串)sss,我们称 sss 合法,当且仅当串 sss 的任意一个长度为 ...

  3. [LOJ#531]「LibreOJ β Round #5」游戏

    [LOJ#531]「LibreOJ β Round #5」游戏 试题描述 LCR 三分钟就解决了问题,她自信地输入了结果-- > -- 正在检查程序 -- > -- 检查通过,正在评估智商 ...

  4. [LOJ#530]「LibreOJ β Round #5」最小倍数

    [LOJ#530]「LibreOJ β Round #5」最小倍数 试题描述 第二天,LCR 终于启动了备份存储器,准备上传数据时,却没有找到熟悉的文件资源,取而代之的是而屏幕上显示的一段话: 您的文 ...

  5. [LOJ#516]「LibreOJ β Round #2」DP 一般看规律

    [LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...

  6. [LOJ#515]「LibreOJ β Round #2」贪心只能过样例

    [LOJ#515]「LibreOJ β Round #2」贪心只能过样例 试题描述 一共有 \(n\) 个数,第 \(i\) 个数 \(x_i\) 可以取 \([a_i , b_i]\) 中任意值. ...

  7. [LOJ#525]「LibreOJ β Round #4」多项式

    [LOJ#525]「LibreOJ β Round #4」多项式 试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k−1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) ...

  8. [LOJ#526]「LibreOJ β Round #4」子集

    [LOJ#526]「LibreOJ β Round #4」子集 试题描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两 ...

  9. [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机)

    [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机) 试题描述 IOI 的比赛开始了.Jsp 和 Rlc 坐在一个角落,这时他们听到了一个异样的声音 …… 接着他们发现自己收 ...

随机推荐

  1. 协程 和 async await

    协程, 是 为了 避免 闭包传递变量 的 性能损耗 而产生  . 如果不是 为了 避免 闭包传递变量 的 性能损耗 ,    线程池 和 Task 已经够了,  不需要 再设计 出 协程 来  . 闭 ...

  2. 学习:Windows数据类型

    WINDOWS API中出现的常见的数据类型有以下几种: 1.DWORD:DWORD用于表示无符号整型的数据类型,实际名为double word,32位 2.HANDLE:HANDLE为32位的数据类 ...

  3. service里无法注入mapper,mapper空指针

    被困扰了一天,终于解决了,记录一下 下面是mapper的代码 @Mapper public interface ProductDao { @Select("select * from pro ...

  4. linux学习16 Linux用户和组管理命令演练和实战应用

    一.上集回顾 1.bash globing,IO重定向及管道 glob:*,?,[],[^] IO重定向: >,>>, 2>,2>> &>,& ...

  5. smashing 开源方便的dashboard 试用

    smashing 一个方便的dashboard 工具,是在Shopify/dashing 上维护的一个版本因为原有的官方团队不在维护了 smashing 使用简单,提供了脚手架同时也有好多人开发了一些 ...

  6. luogu P2353 背单词

    二次联通门 : luogu P2353 背单词 一眼看过去, 卧槽,AC自动机板子题 写完后T成SB 卧槽10^6 做个篮子啊 重构思路... 恩..Hash + 莫队... 恶心啊.. 找xxy d ...

  7. javascript利用canvas解析图片中的二维码

    本方法两种应用方式:一种使用canvas解析本站图片中的二维码,canvas有同源策略限制,只能处理本站图片.另一种处理文件选择中的图片二维码. 第一种使用场景可以换成像微信中一样,长按图片识别二维码 ...

  8. Java代码题目:计算奖金和完全平方数

    1.计算奖金 题目:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%:2 ...

  9. mac切图

    1.按住command键位, 两只手指点击需要切的图 2.再在右边栅格化图层 3.选中需要剪切的图层.command+c 和command+n和 command+v OK 切整张图.先 option ...

  10. Excel填坑[0]

    Excel填坑[0] 本着一天水一贴的原则(放p),我又来填坑了.今天做一个很简单的排队图,虽然不难,但因为手机显示问题折腾了半天.感觉做图做表格不仅仅是靠技术,更重要的是思维. 就是这张图,看起来平 ...