$ \color{#0066ff}{ 题目描述 }$

hsezoi 巨佬 olinr 喜欢 van 毛毛虫,他定义毛毛虫是一棵树,满足树上存在一条树链,使得树上所有点到这条树链的距离最多为 1。 给定 n 。现在请你求出 n 个点、有标号的毛毛虫的数量。答案对 998244353 取模。

\(\color{#0066ff}{输入格式}\)

输入只有一行一个整数 n 。

\(\color{#0066ff}{输出格式}\)

输出一行,表示答案。

\(\color{#0066ff}{输入样例}\)

5

\(\color{#0066ff}{输出样例}\)

125

\(\color{#0066ff}{数据范围与提示}\)

对于 40% 的数据,对于第 \(i\) 个测试点有 \(n=i+4\)。

对于 100% 的数据,\(n\le 10^5\) 。

\(\color{#0066ff}{题解}\)

首先说一句,我很弱

对于一个毛毛虫,我们考虑毛毛虫的一个节,就是那条链上的一个点,可以有一些点接在它身上,假如说有k个点, 那么方案数就是k,(k个点中的一个作为毛毛虫的一节,剩下的k-1个挂在那个点上)

于是它的生成函数\(\begin{aligned}A(x)=\sum_{i\ge 1}i*\frac{x^i}{i!}=\sum_{i\ge 1}\frac{x^i}{(i-1)!}\end{aligned}\)(可以只有自己,没有点挂上去)

还有两个特殊点,就是这条链的两端,我们强制它至少挂上一个点,就是\(\begin{aligned}B(x)=\sum_{i\ge 2}\frac{x^i}{(i-1)!}\end{aligned}\)

然而你发现,少了菊花的情况,但是菊花的情况好统计,就是n

因此答案就是\(B(x)*\frac{1}{1-A(x)}*B(x)\)的第n项乘上n的阶乘除以2(正反算一个)再加上n

\(n\le 2\)要特判,然而并没有这样的数据

#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
using std::vector;
const int mod = 998244353;
const int maxn = 4e6 + 10;
int r[maxn], len;
LL ksm(LL x, LL y) {
LL re = 1LL;
while(y) {
if(y & 1) re = re * x % mod;
x = x * x % mod;
y >>= 1;
}
return re;
}
void FNTT(vector<int> &A, int flag) {
A.resize(len);
for(int i = 0; i < len; i++) if(i < r[i]) std::swap(A[i], A[r[i]]);
for(int l = 1; l < len; l <<= 1) {
int w0 = ksm(3, (mod - 1) / (l << 1));
for(int i = 0; i < len; i += (l << 1)) {
int w = 1, a0 = i, a1 = i + l;
for(int k = 0; k < l; k++, a0++, a1++, w = 1LL * w * w0 % mod) {
int tmp = 1LL * A[a1] * w % mod;
A[a1] = ((A[a0] - tmp) % mod + mod) % mod;
A[a0] = (A[a0] + tmp) % mod;
}
}
}
if(flag == -1) {
std::reverse(A.begin() + 1, A.end());
int inv = ksm(len, mod - 2);
for(int i = 0; i < len; i++) A[i] = 1LL * A[i] * inv % mod;
}
}
vector<int> operator * (const vector<int> &A, const vector<int> &B) {
int tot = A.size() + B.size() - 1;
vector<int> C = A, D = B;
for(len = 1; len <= tot; len <<= 1);
for(int i = 0; i < len; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) * (len >> 1));
FNTT(C, 1), FNTT(D, 1);
vector<int> ans;
ans.resize(len);
for(int i = 0; i < len; i++) ans[i] = 1LL * C[i] * D[i] % mod;
FNTT(ans, -1);
ans.resize(tot);
return ans;
}
vector<int> operator - (const vector<int> &A, const vector<int> &B) {
vector<int> ans;
for(int i = 0; i < (int)std::min(A.size(), B.size()); i++) ans.push_back(A[i] - B[i]);
if(A.size() < B.size()) for(int i = A.size(); i < (int)B.size(); i++) ans.push_back(-B[i]);
if(A.size() > B.size()) for(int i = B.size(); i < (int)A.size(); i++) ans.push_back(A[i]);
return ans;
}
vector<int> inv(const vector<int> &A) {
if(A.size() == 1) {
vector<int> ans;
ans.push_back(ksm(A[0], mod - 2));
return ans;
}
int n = A.size(), _ = (n + 1) >> 1;
vector<int> ans, B = A;
ans.push_back(2);
B.resize(_);
B = inv(B);
ans = B * (ans - A * B);
ans.resize(n);
return ans;
}
int fac[maxn];
int main() {
int n = in();
fac[0] = 1;
for(int i = 1; i <= n; i++) fac[i] = 1LL * fac[i - 1] * i % mod;
std::vector<int> a, b;
a.resize(n + 1, 0), b.resize(n + 1, 0);
for(int i = 1; i <= n; i++) a[i] = mod - ksm(fac[i - 1], mod - 2);
for(int i = 2; i <= n; i++) b[i] = ksm(fac[i - 1], mod - 2);
a[0]++;
a = inv(a);
a = b * a * b;
printf("%lld\n", (1LL * a[n] * fac[n] % mod * ksm(2, mod - 2) % mod + n) % mod);
return 0;
}

loj #6570. 毛毛虫计数的更多相关文章

  1. [LOJ 6185]烷基计数

    Description 众所周知,大连 24 中是一所神奇的学校,在那里,化竞的同学很多都擅长写代码. 有一天,化学不及格的胡小兔向化竞巨佬晴岚请教化学题: “n 个碳原子的烷基共有多少种同分异构体? ...

  2. loj6570 毛毛虫计数(生成函数FFT)

    link 巨佬olinr的题解 <-- olinr很强 考虑生成函数 考虑直径上点数>=4的毛毛虫的直径,考虑直径中间那些节点以及他上面挂的那些点的EGF \(A(x)=\sum_{i\g ...

  3. LOJ #10070 最小生成树计数

    一道mst-- 最开始是毫无头绪,于是就点开了--->题解 大部分题解都是矩阵树--然而第一篇题解告诉了我们暴搜也能过( 思路大概是说,对于一个图\(G\),它的所有最小生成树的相同权值的边的数 ...

  4. LOJ#2320 生成树计数

    解:讲一个别的题解里我比较难以理解的地方,就是为什么可以把这两个东西合起来看成某一个连通块指数是2m而别的指数都是m. 其实很好理解,但是别人都略过了......把后面的∑提到∏的前面,然后展开,也可 ...

  5. LOJ #6538. 烷基计数 加强版 加强版(生成函数,burnside引理,多项式牛顿迭代)

    传送门. 不妨设\(A(x)\)表示答案. 对于一个点,考虑它的三个子节点,直接卷起来是\(A(x)^3\),但是这样肯定会计重,因为我们要的是无序的子节点. 那么用burnside引理,枚举一个排列 ...

  6. LOJ6071. 「2017 山东一轮集训 Day5」字符串 [SAM]

    LOJ 思路 这种计数题显然是要先把每一个合法的串用唯一的方法表示出来.(我连这都没想到真是无可救药了) 如何唯一?容易想到把前缀尽可能多地在第一个串填掉,然后填第二个,第三个-- 如何做到这样?可以 ...

  7. Loj 2320.「清华集训 2017」生成树计数

    Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...

  8. loj#2665. 「NOI2013」树的计数

    目录 题目链接 题解 代码 题目链接 loj#2665. 「NOI2013」树的计数 题解 求树高的期望 对bfs序分层 考虑同时符合dfs和bfs序的树满足什么条件 第一个点要强制分层 对于bfs序 ...

  9. loj#6076「2017 山东一轮集训 Day6」三元组 莫比乌斯反演 + 三元环计数

    题目大意: 给定\(a, b, c\),求\(\sum \limits_{i = 1}^a \sum \limits_{j = 1}^b \sum \limits_{k = 1}^c [(i, j) ...

随机推荐

  1. Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺

    更新 其实本文的初衷是为了获取淘宝的非匿名旺旺,在淘宝详情页的最下方有相关评论,含有非匿名旺旺号,快一年了淘宝都没有修复这个. 可就在今天,淘宝把所有的账号设置成了匿名显示,SO,获取非匿名旺旺号已经 ...

  2. Ubuntu 安装QT5 后编译程序报错: FindQt5Widgets.cmake

    安装QT5.4后,需要编译一个C++程序. Cmakelist 有find_package(Qt5Widgets REQUIRED),cmake 报错如下: CMake Error at CMakeL ...

  3. [Jenkins] 执行SoapUI的task,设置邮件内容为HTML+CSS

    设置邮件内容:Default Content <span style="font-family:verdana;font-size:16px;color:black;font-weig ...

  4. 原型设计工具Mockplus新年送福利,见者有份

    为感谢大家对Mockplus的喜爱与支持,给大家送福利了! 送送送,见者有份! 参与活动,三分钟时间,均可最高获赠专业版1个月使用时间.见者有份! 领福利步骤: 1. 扫码关注微信公众号:Mockpl ...

  5. HBase预分区方法

    (what)什么是预分区? HBase表在刚刚被创建时,只有1个分区(region),当一个region过大(达到hbase.hregion.max.filesize属性中定义的阈值,默认10GB)时 ...

  6. hdu 1686 KMP算法

    题意: 求子串w在T中出现的次数. kmp算法详解:http://www.cnblogs.com/XDJjy/p/3871045.html #include <iostream> #inc ...

  7. React相关知识和经验的碎片化记录

    React相关知识和经验的碎片化记录 1.Warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a chil ...

  8. 实践作业4---DAY4阶段三。

    阶段三:给出结论 这一阶段,我们首先列表从核心功能.细节.用户体验.辅助功能差异化功能.软件的适应性和成长性展开.我们得结论前参考了权威网站数据.并自己也做了相应分析. 结论:经过这么多工作,这个软件 ...

  9. QT学习之事件处理

    Qt事件机制 Qt程序是事件驱动的, 程序的每个动作都是由幕后某个事件所触发.. Qt事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. Qt事件的类型很多, 常见的qt的事件如下: 键盘事 ...

  10. (1)WePHP 开启WePHP

    新建入口文件index.php,定义新项目的目录地址APP_PATH,引入WePHP项目入口文件 <?php define('APP_PATH','./index/'); require_onc ...