考虑在 \(n\) 个节点的树中,树根作为 \(lca\) 对答案的贡献,显然就是在左子树的叶子中选出一个非空集的方案乘上右子树的方案。

\[w(n, id) = id \cdot (2 ^ {L\_Leaf} - 1) \cdot (2 ^ {R\_Leaf} - 1)
\]

进而得到一个 \(O(N)\) 的 \(dp\),其中 \(ls = \lceil \dfrac{n}{2} \rceil\),\(rs = \lfloor \dfrac{n}{2} \rfloor\)。

\[dp(n, id) = w(n, id) + dp(ls, 2\cdot id) + dp(rs, 2\cdot id + 1)
\]

观察状态参数,可以发现在一次求解中 \(id\) 有 \(O(N)\) 个,而 \(n\) 只有 \(O(\log N)\) 个,一个直观的想法是把 \(id\) 从状态方程中剥离出去。

不妨手玩一下这个式子。

\[\begin{aligned}
dp(n, id) &= w(n, id) + dp(ls, 2\cdot id) + dp(rs, 2\cdot id + 1) \\
&= t(n) \cdot id + dp(ls, 2\cdot id) + dp(rs, 2\cdot id + 1) \\
&= t(n) \cdot id + t(ls) \cdot 2\cdot id + t(rs) \cdot (2\cdot id + 1) + (dp \ldots) \\
&= (t(n) + 2 \cdot t(ls) + 2 \cdot t(rs) + 4 \cdot \ldots) \cdot id + (t(rs) + \ldots)
\end{aligned}
\]

能够得到整个状态方程为 \(id\) 的一次函数,只需维护 \(k(n)\) 和 \(b(n)\) 就好了。

\[dp(n, id) = k(n) \cdot id + b(n)
\]

由于

\[\begin{aligned}
dp(n, id) &= t(n) \cdot id + dp(ls, 2\cdot id) + dp(rs, 2\cdot id + 1) \\
&= t(n) \cdot id + k(ls) \cdot 2\cdot id + b(ls) + k(rs) \cdot (2\cdot id + 1) + b(rd)
\end{aligned}
\]

所以

\[k(n) = t(n) + 2 \cdot k(ls) + 2 \cdot k(rs)
\]
\[b(n) = b(ls) + k(rs) + b(rs)
\]
map<ll, pll> mp;

pll calc(ll n) {
if(mp.find(n) != mp.end()) return mp[n];
auto [lk, lb] = calc((n + 1) / 2);
auto [rk, rb] = calc(n / 2);
ll t = (q_pow(2, (n + 1) / 2) - 1) * (q_pow(2, n / 2) - 1) % P;
ll k = (t + 2 * lk + 2 * rk) % P;
ll b = (lb + rk + rb) % P;
/*
f[n][id] = t * id + f[ls][lsid] + f[rs][rsid]
*/
return mp[n] = {k % P, b % P};
} void solve() {
ll n;
cin >> n;
auto [k, b] = calc(n);
cout << (k + b) % P << '\n';
} int main() {
int T; cin >> T;
mp[1] = {1, 0};
while(T --) solve();
return 0;
}

ccf 赶紧支持 c++17

随机推荐

  1. react-naive工作原理

    react-naive工作原理是从react的工作原理衍生出来的 react的工作原理 在react中,virtual dom 就像一个中间层,介于开发者描述的视图与实际在页面上渲染的视图之间.为了在 ...

  2. veriog之四位全加器

    verilog之四位全加器 1.简易代码 module adder_4bit ( cout,sum,ina,inb,cin ); output[3:0] sum; output cout; input ...

  3. exist和left join 性能对比

    今天遇到一个性能问题,再调优过程中发现耗时最久的计划是exist 部分涉及的三个表. 然后计划用left join 来替换exist,然后查询了很多资料,大部分都说exist和left join 性能 ...

  4. AndroidStudio开发体温上报安卓APP------问题总结

    总结一下出现的问题: 1.首先是AndroidStudio的配置问题 在这里可以看sdk版本配置 这里可以看gradle的版本信息和下载目录 AndroidStudio手动配置gradle 1.首先编 ...

  5. Python 代码混淆工具概述

    在保护Python代码安全方面,有多种混淆工具可供选择,包括 Cython, Nuitka, Pyminifier 和 IPA guard.本文将介绍这些工具的特点和适用情况,以及在实际应用中的注意事 ...

  6. OpenHarmony社区运营报告(2022年10月)

    本月快讯 ● <深圳市推动软件产业高质量发展的若干措施>于10月24日发布. ● 社区共发展逾5000位贡献者累计为社区提交超过11万个PR,深圳市优博终端科技有限公司(以下简称" ...

  7. [UAC]C++判断某进程是否有管理员权限

    BOOL IsAdminProcess(UINT PID) { if (PID <= 0) PID = GetCurrentProcessId(); HANDLE hProcess = Open ...

  8. redis 简单整理——redis 的列表基本结构和命令[四]

    前言 简单整理一下redis的列表. 正文 列表(list)类型是用来存储多个有序的字符串,如图2-18所示,a. b.c.d.e五个元素从左到右组成了一个有序的列表,列表中的每个字符串 称为元素(e ...

  9. 力扣1069(MySQL)-产品分析Ⅱ(简单)

    题目: 编写一个 SQL 查询,按产品 id product_id 来统计每个产品的销售总量. 查询结果格式如下面例子所示:  解题思路: 没有用到product表,直接在sales表中使用聚合函数: ...

  10. 力扣290(java)-单词规律(简单)

    题目: 给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律. 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接 ...