Educational Codeforces Round 127 (Rated for Div. 2) E. Preorder
设是以结点为根的方案数,设左子树的根为,右子树的根为,那么如果左右子树完全相同,那么我们交换左右子树对方案没有任何影响,都是:
如果左右子树不相同,那么则多出的贡献,所以方案数为。
最重要的就是如何判断两个子树是不是完全相同的,这里用到树哈希,参考大佬们的哈希函数:
其中,是两个不同的质数,因为对哈希基本没有研究,所以我直接取了131,1331,幸运没有被卡。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const int N = (1 << 18) + 10, Mod = 998244353;
ull P1 = 131, P0 = 13131;
ull Hash[N];
ll n;
ll f[N];
ull pre1[25], pre0[25];
string s;
void dfs(ll u, ll depth) {
if (u * 2 >= ((1 << n) - 1)) { //到了叶子结点
f[u] = 1;
Hash[u] = ((s[u] - 'A') ? pre1[depth] : pre0[depth]);
return;
}
dfs(u * 2ll, depth + 1);
dfs(u * 2ll + 1, depth + 1);
Hash[u] = Hash[u << 1] * Hash[u << 1 | 1] + ((s[u] - 'A') ? pre1[depth] : pre0[depth]);
f[u] = f[u << 1] * f[u << 1 | 1] % Mod;
if (Hash[u << 1] != Hash[u << 1 | 1]) {
f[u] = f[u << 1] * f[u << 1 | 1] % Mod * 2 % Mod;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
pre1[1] = P1;
for (int i = 2; i <= 20; i++) {
pre1[i] = pre1[i - 1] * P1;
}
pre0[1] = P0;
for (int i = 2; i <= 20; i++) {
pre0[i] = pre0[i - 1] * P0;
}
cin >> n;
cin >> s;
s = "0" + s;
dfs(1, 1);
//cout << Hash[4] << " " << Hash[5] << "\n";
cout << f[1] << "\n";
return 0;
}
标签:
哈希
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端