哈希-蔡老板分果子
Posted ghcred
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈希-蔡老板分果子相关的知识,希望对你有一定的参考价值。
#238. 蔡老板分果子
春天来了,万物复苏,动物们又到了发情的季节。蔡老板终于下定决心砍下了自家后院的两棵果树,并决定和自己喜欢的人一起分享果树上的果子。
这两棵果树一棵是长生果树另一棵是人参果树,两棵树上都有 nn 个果子,编号为 1∼n1∼n,并分别由 n−1n−1 段树枝连接起来。 为了把果子分成两份,蔡老板决定再两棵树上各砍一刀,分别砍断一根树枝把两棵树上的果子各分成两个部分。之后,对于每一棵果树,蔡老板会选择 11 号果子所在的那一部分。显然这样分果子一共有 (n−1)2(n−1)2 种分法,而蔡老板想知道,有多少种切割方法,使得蔡老师拿到的长生果和人参果具有相同的标号集合。
输入格式
第一行一个正整数 nn 表示两棵树的大小。
接下来 n−1n−1 行每行两个正整数表示长生果树上的边。
接下来 n−1n−1 行每行两个正整数表示人参果树上的边。
输出格式
输出一行一个正整数表示蔡老板关心的切割方法的数目。
样例1
input
4 1 2 2 3 3 4 1 2 1 3 3 4
output
2
explanation
第一种切割方法:第一棵树上切 (2,3)(2,3),第二棵树上切 (1,3)(1,3),这样蔡老师拿到的长生果和人参果集合都是 {1,2}{1,2};
第二种切割方法:第一棵树上切 (3,4)(3,4),第二棵树上切 (3,4)(3,4),这样蔡老师拿到的长生果和人参果集合都是 {1,2,3}{1,2,3}。
样例2
input
6 1 2 1 3 2 4 2 5 3 6 1 4 4 2 4 5 2 3 3 6
output
3
样例3
见样例数据下载
限制与规定
对于全部数据 1≤n≤2×105.1≤n≤2×105.
本题采用捆绑测试,只有通过一个子任务的全部测试点才可以获得该子任务的分数,子任务及限制如下表所示:
子任务编号 | 分值 | nn | 其他限制 |
---|---|---|---|
1 | 4 | ≤10≤10 | 无 |
2 | 19 | ≤100≤100 | 无 |
3 | 20 | ≤103≤103 | 无 |
4 | 21 | ≤2×105≤2×105 | 保证所有点的度数不超过 22 |
5 | 36 | ≤2×105≤2×105 | 无 |
时间限制:1s1s
空间限制:256MB256MB
下载
需要设计一个哈希函数与树的形态和父子关系无关。想到了 (ap+bp)%q 这类哈希函数,会被卡掉。正解是直接用 xor 哈希,然后提前把 [1, N] 映射到一个 unsigned long long 的整数。据说(也可以感性感受到)这样的好处是每一位的影响是独立的。也就是说,只有每一位都冲突,两个哈希函数才可能冲突。这样就可以过。代码里把幂数和和异或和作为两个参数搞了一个双哈,不过真正起作用的是异或和。
1 #include <stdio.h> 2 #include <algorithm> 3 #include <vector> 4 #include <stdlib.h> 5 6 using namespace std; 7 8 typedef unsigned long long ull; 9 10 const int _N = 220000; 11 const ull P = 1e9+7; 12 13 ull hs[_N]; 14 vector<int> G[2][_N]; 15 int N; 16 17 struct data { 18 ull a, b; 19 20 bool operator < (const data &tmp) const 21 { 22 return a == tmp.a ? b < tmp.b : a < tmp.a; 23 } 24 25 bool operator == (const data &tmp) const 26 { 27 return a == tmp.a && b == tmp.b; 28 } 29 } A[2][_N]; 30 31 ull Mont(ull a) 32 { 33 a %= P; 34 ull t = 1, b = 131; 35 while (b) { 36 if (b & 1) t = t*a%P; 37 b >>= 1, a = a*a%P; 38 } 39 return t; 40 } 41 42 void DFS(int id, int node, int dad) 43 { 44 A[id][node].a = hs[node], A[id][node].b = Mont(hs[node]); 45 for (int i = G[id][node].size()-1; i >= 0; --i) { 46 int v = G[id][node][i]; 47 if (v != dad) { 48 DFS(id, v, node); 49 A[id][node].a = A[id][node].a^A[id][v].a, A[id][node].b = (A[id][node].b+A[id][v].b)%P; 50 } 51 } 52 return; 53 } 54 55 inline ull umul(int a, int b) { return (ull)a * b; } 56 57 void Ins(int id, int x, int y) 58 { 59 G[id][x].push_back(y), G[id][y].push_back(x); 60 return; 61 } 62 63 int main() 64 { 65 int i, j, id; 66 srand(19260817); 67 scanf("%d", &N); 68 for (i = 1; i <= N; ++i) hs[i] = umul(umul(rand(), rand()), rand())+rand()%97; 69 for (id = 0; id <= 1; ++id) 70 for (i = 1; i < N; ++i) { 71 int x, y; 72 scanf("%d%d", &x, &y); 73 Ins(id, x, y); 74 } 75 for (id = 0; id <= 1; ++id) 76 DFS(id, 1, -1), sort(A[id]+1, A[id]+1+N); 77 i = j = 1; 78 int ans = 0; 79 while (i <= N && j <= N) { 80 if (A[0][i] == A[1][j]) ++ans, ++i; 81 else if (A[0][i] < A[1][j]) ++i; 82 else ++j; 83 } 84 printf("%d ", ans-1); 85 return 0; 86 }
以上是关于哈希-蔡老板分果子的主要内容,如果未能解决你的问题,请参考以下文章