Solution -「NOI Simu.」树
\(\mathscr{Description}\)
给定 \(n\), 集合 \(\{a_m\}\), 称一棵无标号但儿子有序的有根树合法, 当且仅当叶子权值存在一个因数在 \(\{a_m\}\) 中, 且叶子点权积不超过 \(n\). 此外, 要求不存在仅含一个儿子的结点. 求有多少棵合法树. 答案模 \(10^9+7\).
\(\mathscr{Solution}\)
令 \(L(x)=\sum_{i}[\exists t\in\{a_m\},~t\mid i]x^i\), \(F(x)\) 为有根树关于叶子乘积和的 GF, 那么
\]
其中卷积是 Dirichlet 卷积. 推一下式子:
\Rightarrow 2F^2(x)-(L(x)+\epsilon)F(x)+L(x)=0\\
\Rightarrow F(x)=\frac{L(x)+\epsilon-\sqrt{L^2(x)-6L(x)+\epsilon}}{4}.
\]
我们想要求 \(F(x)\) 前缀系数和, 如果能求出 \(L^2(x)-6L(x)+\epsilon\) 的 \(\sqrt n\) 个前缀和, 并以此算出开根后 \(n\) 处的前缀和, 实际上就结束了.
不太平凡的只有 Dirichlet 开根, 令 \(G^2(x)=T(x)=L^2(x)-6L(x)+\epsilon\), 那么
\Rightarrow 2S_g(m)=S_t(m)-\sum_{i=2}^{m/2}g_iS_g(m/i)+S_g(m/2+1).
\]
经过暴力卷积预处理分块, 可以做到 \(\mathcal O(n^{2/3}\ln^{1/3}n)\).
\(\mathscr{Code}\)
/*+Rainybunny+*/
#include <bits/extc++.h>
#define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
#define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i)
typedef long long LL;
const int MOD = 1e9 + 7, MAXM = 8, INV2 = 500000004, INV4 = 250000002;
const int THRES = 2e6, MAXSQRT = 1e5; // (n/ln(n))^{2/3}.
// const int THRES = 5;
LL n, lcm[1 << MAXM];
int sn, m, a[MAXM + 5], L[THRES + 5], L2[THRES + 5], G[THRES + 5];
int pn, pr[THRES + 5], mp[THRES + 5];
bool npr[THRES + 5];
inline int mul(const int u, const int v) { return 1ll * u * v % MOD; }
inline void subeq(int& u, const int v) { (u -= v) < 0 && (u += MOD); }
inline int sub(int u, const int v) { return (u -= v) < 0 ? u + MOD : u; }
inline void addeq(int& u, const int v) { (u += v) >= MOD && (u -= MOD); }
inline int add(int u, const int v) { return (u += v) < MOD ? u : u - MOD; }
inline int mpow(int u, int v) {
int ret = 1;
for (; v; u = mul(u, u), v >>= 1) ret = mul(ret, v & 1 ? u : 1);
return ret;
}
inline void init() {
rep (i, 2, THRES) {
if (!npr[i]) mp[pr[++pn] = i] = i;
for (int j = 1, t; j <= pn && (t = i * pr[j]) <= THRES; ++j) {
npr[t] = true, mp[t] = pr[j];
if (!(i % pr[j])) break;
}
}
rep (S, 1, (1 << m) - 1) {
lcm[S] = 1;
rep (i, 0, m - 1) if (S >> i & 1) {
lcm[S] = lcm[S] / std::__gcd(lcm[S], 0ll + a[i]) * a[i];
}
if (__builtin_parity(S)) rep (i, 1, THRES / lcm[S]) ++L[lcm[S] * i];
else rep (i, 1, THRES / lcm[S]) --L[lcm[S] * i];
}
rep (i, 1, THRES) rep (j, 1, THRES / i) addeq(L2[i * j], mul(L[i], L[j]));
G[1] = 1;
rep (i, 2, THRES) {
static int pc, pv[30], alp[30]; pc = 0;
for (int t = i; t > 1;) {
pv[++pc] = mp[t], alp[pc] = 0;
while (mp[t] == pv[pc]) ++alp[pc], t /= pv[pc];
}
std::function<int(int, int)>
contri = [&](const int x, int v)->int {
if (x > pc) return mul(G[v], G[i / v]);
int ret = 0;
rep (j, 1, alp[x]) addeq(ret, contri(x + 1, v)), v *= pv[x];
return add(ret, contri(x + 1, v));
};
G[i] = mul(sub(sub(L2[i], mul(6, L[i])), contri(1, 1)), INV2);
}
rep (i, 1, THRES) {
addeq(L[i], L[i - 1]), addeq(L2[i], L2[i - 1]), addeq(G[i], G[i - 1]);
}
}
inline int id(const LL x) { return x <= sn ? x : sn + n / x; }
inline int calcL(const LL m) {
static int mem[MAXSQRT * 2 + 5];
static int vis[MAXSQRT * 2 + 5];
if (m <= THRES) return L[m];
int h = id(m);
if (vis[h]) return mem[h];
int& ret = mem[h]; vis[h] = true;
rep (S, 1, (1 << ::m) - 1) {
(__builtin_parity(S) ? addeq : subeq)(ret, m / lcm[S] % MOD);
}
return ret;
}
inline int calcL2(const LL m) {
static int mem[MAXSQRT * 2 + 5];
static int vis[MAXSQRT * 2 + 5];
if (m <= THRES) return L2[m];
int h = id(m);
if (vis[h]) return mem[h];
int& ret = mem[h] = 0; vis[h] = true;
for (LL l = 2, r; l <= m; l = r + 1) {
r = m / (m / l);
addeq(ret, mul(calcL(m / l), sub(calcL(r), calcL(l - 1))));
}
return ret;
}
inline int calcG(const LL m) {
static int mem[MAXSQRT * 2 + 5];
static int vis[MAXSQRT * 2 + 5];
if (m <= THRES) return G[m];
int h = id(m);
if (vis[h]) return mem[h];
int& ret = mem[h] = add(sub(calcL2(m), mul(6, calcL(m))), 1); vis[h] = 1;
for (LL l = 2, r; l <= m; l = r + 1) {
r = m / (m / l);
if (m / l == 1) addeq(ret, calcG(l - 1));
else subeq(ret, mul(calcG(m / l), sub(calcG(r), calcG(l - 1))));
}
ret = mul(ret, INV2);
return ret;
}
int main() {
freopen("tree.in", "r", stdin);
freopen("tree.out", "w", stdout);
scanf("%lld %d", &n, &m), sn = sqrt(n);
rep (i, 0, m - 1) scanf("%d", &a[i]);
init();
int ans = mul(sub(add(calcL(n), 1), calcG(n)), INV4);
printf("%d\n", ans);
return 0;
}
Solution -「NOI Simu.」树的更多相关文章
- Solution -「NOI 2020」「洛谷 P6776」超现实树
\(\mathcal{Description}\) Link. 对于非空二叉树 \(T\),定义 \(\operatorname{grow}(T)\) 为所有能通过若干次"替换 \( ...
- Solution -「NOI 2018」「洛谷 P4768」归程
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的无向连通图,边形如 \((u,v,l,a)\).每次询问给出 \(u,p\),回答 ...
- Solution -「NOI 2021」「洛谷 P7740」机器人游戏
\(\mathcal{Description}\) Link. 自己去读题面叭~ \(\mathcal{Solution}\) 首先,参悟[样例解释 #2].一种暴力的思路即为钦定集合 \ ...
- Solution -「NOI 2016」「洛谷 P1587」循环之美
\(\mathcal{Description}\) Link. 给定 \(n,m,k\),求 \(x\in [1,n]\cap\mathbb N,y\in [1,m]\cap \mathbb ...
- Solution -「NOI 2012」「洛谷 P2050」美食节
\(\mathcal{Description}\) Link. 美食节提供 \(n\) 种菜品,第 \(i\) 种的需求量是 \(p_i\),菜品由 \(m\) 个厨师负责制作,第 \(j\) ...
- Solution -「NOI 2008」「洛谷 P3980」志愿者招募
\(\mathcal{Description}\) Link. 一项持续 \(n\) 天的任务,第 \(i\) 天需要至少 \(a_i\) 人工作.还有 \(m\) 种雇佣方式,第 \(i\) ...
- loj#2054. 「TJOI / HEOI2016」树
题目链接 loj#2054. 「TJOI / HEOI2016」树 题解 每次标记覆盖整棵字数,子树维护对于标记深度取max dfs序+线段树维护一下 代码 #include<cstdio> ...
- AC日记——#2054. 「TJOI / HEOI2016」树
#2054. 「TJOI / HEOI2016」树 思路: 线段树: 代码: #include <cstdio> #include <cstring> #include < ...
- Solution -「ARC 104E」Random LIS
\(\mathcal{Description}\) Link. 给定整数序列 \(\{a_n\}\),对于整数序列 \(\{b_n\}\),\(b_i\) 在 \([1,a_i]\) 中等概率 ...
- Solution -「BZOJ 4316」小C的独立集
\(\mathcal{Description}\) Link. 求包含 \(n\) 个结点 \(m\) 条边的仙人掌的最大独立集. \(n\le5\times10^4\),\(m\le6\ ...
随机推荐
- 指针进阶(C语言终)
1. sizeof和strlen的对比 1.1 sizeof 在学习操作符的时候,我们学习了sizeof , sizeof 计算变量所占内存内存空间大小的,单位是 字节,如果操作数是类型的话,计算的是 ...
- C++之OpenCV入门到提高003:矩阵的掩膜(Mask)处理
一.介绍 今天是这个系列<C++之 Opencv 入门到提高>得第三篇文章.今天这篇文章也不难,主要介绍如何使用 Opencv 对图像进行掩膜处理,提高图像的对比度.在这个过程中,我们可以 ...
- Antlr4 语法解析器(下)
Antlr4 的两种AST遍历方式:Visitor方式 和 Listener方式. Antlr4规则文法: 注释:和Java的注释完全一致,也可参考C的注释,只是增加了JavaDoc类型的注释: 标志 ...
- AI运动小程序开发常见问题集锦一
截止到现在写博文时,我们的AI运动识别小程序插件已经迭代了23个版本,成功应用于健身.体育.体测.AR互动等场景:为了让正在集成或者计划进行功能扩展优化的用户,少走弯路.投入更少的开发资源,我们归集了 ...
- nano编辑器保存退出
nano的编辑器保存推出 使用 ctrl x 然后提示Y N 是否保存 写入,输入Y即可 然后再Enter 确认就可以了
- 符合ASTM标准的雨流计数法及其不同的改进方法
随着研究的深入,人们发现采用时间序列计算载荷谱太麻烦了,处理的工作量太大,我们不需要将每个时刻点的载荷都做运算,疲劳计算只需要提供幅值.均值和循环次数,鉴于此发展出了很多不同的计数方法,雨流法是最常见 ...
- 静态分析工具及使用总结(二)CheckStyle
这里主要介绍三种开源的工具,PMD.CheckStyle和FindBugs,着重是在Ant里的调用,据说商业软件JTest也是著名的代码分析工具,哈哈,要花钱的没有用过. Checkstyle (ht ...
- 聊一下怎么十分钟速水CVE
题目是真的.今天晚上刚接触关于CVE的审计和提交.只能说:牛逼的是真牛逼,水的是真水. 我接下来教你,怎么在10分钟里找到一个CVE的中危漏洞并且提交.然后你就可以去咸鱼接单了,一个一铂快 打开htt ...
- manim边做边学--多面体
在Manim中,对于多面体,有一系列封装好的类可以直接使用. 使用它们,可以方便快速的构建正多面体: Polyhedron:通过顶点和面的参数构建任意多面体 Tetrahedron:四面体 Octah ...
- MQ系列 | RabbitMQ 消息确认机制
RabbitMQ 消息确认机制 温馨提示:基于JDK17.SpringBoot 2.1.8.RELEASE 版本,由于RabbitMQ 在 SpringBoot3+ 的配置项有所不同, 所以请严格按照 ...