洛谷P2441 角色属性树 题解
题目链接:P2441 角色属性树
题意:
绪萌同人社是一个有趣的组织,该组织结构是一个树形结构。有一个社长,直接下属一些副社长。每个副社长又直接下属一些部长……。
每个成员都有一个萌点的属性,萌点属性是由一些质数的萌元素乘积构成(例如,猫耳的值是 $2$,弱气的值是 $3$,黄毛的值是 $5$,病娇的值是 $7$,双马尾的值是 $11$ 等等)
举个例子,正妹是双份的猫耳,而且有一份弱气,她的属性值为 $2\times 2\times 3=12$。
现在组员关心一个问题,希望知道离自己最近且有相同萌元素上司是谁,例如,属性值为 $2、4、6、45$ 这样的属性值都算是和正妹有相同的属性。
然而,组员可能会随时变化自己的属性。啊。。感觉好麻烦啊。。
输入格式:
第一行,$n,k$ 表示成员数与询问的次数
第二行,$n$ 个数,分别是 $1$ 到 $n$ 号成员的属性值
接下来 $n-1$ 行,$x_i,y_i$ 表示 $x_i$ 是 $y_i$ 的上司。
接下来来 $k$ 行,有两种情况
$1\ u_i$:询问离 $u_i$ 成员最近且有相同萌元素上司。
$2\ u_i$:$a$ 更改 $u_i$ 的属性值为 $a$。
输出格式:
对于每个 $1$ 类型的询问,输出符合要求的编号。如果没有符合要求的编号,输出 $-1$。
数据范围:
本题测试数据随机,可能是假题。
对于 $100\%$ 的数据,$n\le 200000$,$k<100000$,修改次数 $\le 50,a_i\le 2^{31}-1$
前置知识:欧拉乘积公式
考虑两个自然数 $a,b$ 互质的概率。
如果 $a,b$ 互质,则 $a,b$ 没有公约数 $2,3,5,\cdots$ ,即
整理一下可得
而众所周知 $\zeta(2)=\frac{\pi^2}{6}$ ,概率即为 $\frac{6}{\pi^2}\approx0.6079271$ 。
于是两个自然数不互质的概率为 $p = 1 - \frac{6}{\pi^2} \approx 0.392$
对于本题,暴力 $k$ 次询问得到答案的概率为 $f(k)=\sum_{0 \le i < k}(1-p)^ip$
计算可知在 $k = 10$ 时 $f(k)\approx0.993105$ ,这已经是非常高的概率了。
因为数据是随机的,所以暴力的复杂度为 $\mathcal{O}(q\log n)$ ,这里的 $\log n$ 是树高
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(2e5 + 15))
int n,q,a[N],fa[N];
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
int dfs(int x, int y)
{
if(x == 0) return -1;
if(gcd(a[x], a[y]) > 1) return x;
return dfs(fa[x], y);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
cin >> n >> q;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1, x, y; i < n; i++) { cin >> x >> y; fa[y] = x; }
for(int i = 1, x, y; i <= q; i++)
{
cin >> x;
if(x == 1) {
cin >> y; cout << dfs(fa[y], y) << '\n';
}else { cin >> x >> y; a[x] = y; }
}
return 0;
}
题外话:
因为没有概率这个标签,所以假装这道题是随机化(总不能说是玄学吧)。