loj #6570. 毛毛虫计数
$ \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. 毛毛虫计数的更多相关文章
- [LOJ 6185]烷基计数
Description 众所周知,大连 24 中是一所神奇的学校,在那里,化竞的同学很多都擅长写代码. 有一天,化学不及格的胡小兔向化竞巨佬晴岚请教化学题: “n 个碳原子的烷基共有多少种同分异构体? ...
- loj6570 毛毛虫计数(生成函数FFT)
link 巨佬olinr的题解 <-- olinr很强 考虑生成函数 考虑直径上点数>=4的毛毛虫的直径,考虑直径中间那些节点以及他上面挂的那些点的EGF \(A(x)=\sum_{i\g ...
- LOJ #10070 最小生成树计数
一道mst-- 最开始是毫无头绪,于是就点开了--->题解 大部分题解都是矩阵树--然而第一篇题解告诉了我们暴搜也能过( 思路大概是说,对于一个图\(G\),它的所有最小生成树的相同权值的边的数 ...
- LOJ#2320 生成树计数
解:讲一个别的题解里我比较难以理解的地方,就是为什么可以把这两个东西合起来看成某一个连通块指数是2m而别的指数都是m. 其实很好理解,但是别人都略过了......把后面的∑提到∏的前面,然后展开,也可 ...
- LOJ #6538. 烷基计数 加强版 加强版(生成函数,burnside引理,多项式牛顿迭代)
传送门. 不妨设\(A(x)\)表示答案. 对于一个点,考虑它的三个子节点,直接卷起来是\(A(x)^3\),但是这样肯定会计重,因为我们要的是无序的子节点. 那么用burnside引理,枚举一个排列 ...
- LOJ6071. 「2017 山东一轮集训 Day5」字符串 [SAM]
LOJ 思路 这种计数题显然是要先把每一个合法的串用唯一的方法表示出来.(我连这都没想到真是无可救药了) 如何唯一?容易想到把前缀尽可能多地在第一个串填掉,然后填第二个,第三个-- 如何做到这样?可以 ...
- Loj 2320.「清华集训 2017」生成树计数
Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...
- loj#2665. 「NOI2013」树的计数
目录 题目链接 题解 代码 题目链接 loj#2665. 「NOI2013」树的计数 题解 求树高的期望 对bfs序分层 考虑同时符合dfs和bfs序的树满足什么条件 第一个点要强制分层 对于bfs序 ...
- loj#6076「2017 山东一轮集训 Day6」三元组 莫比乌斯反演 + 三元环计数
题目大意: 给定\(a, b, c\),求\(\sum \limits_{i = 1}^a \sum \limits_{j = 1}^b \sum \limits_{k = 1}^c [(i, j) ...
随机推荐
- 英文单词cipher 和password的区别,用法有什么不同,
['saɪfə(r)] cipher 指一套密码系统,比如电影<风声>中破译的那个系统叫cipher:password 则指进入的指令,比如你的qq密码,电脑密码等叫password.总之 ...
- 线上应用故障排查:高CPU占用
转自:hankchen,http://www.blogjava.net/hankchen 一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环. 以我们最近出现的一个实际故障 ...
- vscode安装dlv插件报错:There is no tracking information for the current branch.
vscode安装dlv插件报错:There is no tracking information for the current branch. https://blog.csdn.net/a7859 ...
- IO引脚复用和映射
1.端口复用 这些外设包括ADC,DAC以及串口等等. 查找STM32F429数据手册可以找到相关IO口的复用功能引脚. 注意:除ADC和DAC要配置成模拟通道外,其他的所有外设都要配置成复用功能.
- 实践作业4---DAY4阶段三。
阶段三:给出结论 这一阶段,我们首先列表从核心功能.细节.用户体验.辅助功能差异化功能.软件的适应性和成长性展开.我们得结论前参考了权威网站数据.并自己也做了相应分析. 结论:经过这么多工作,这个软件 ...
- 黑盒测试实践-任务进度-Day05
任务进度11-30 使用工具 selenium 小组成员 华同学.郭同学.穆同学.沈同学.覃同学.刘同学 任务进度 经过了前两天的学习任务的安排,以下是大家的任务进度: 华同学(任务1) 1.由于昨天 ...
- myeclipse如何取消对某个文件的验证
在用Myeclipse导入新工程或在写代码时,最郁闷的就是它对js,jsp,html的验证太严格了,有时会呈现一个红叉或者一个黄色的感慨号,一运行就报Cannot return from outsid ...
- Centos6 hadoop2.6.0安装笔记
系统环境: linux:Centos6-64bit hadoop:hadoop2.6.0 jdk:1.6.45 集群方式安装 一台master,3台slave master 192.168.111.1 ...
- zrender源码分析3--初始化Painter绘图模块
接上次分析到初始化ZRender的源码,这次关注绘图模块Painter的初始化 入口1:new Painter(dom, this.storage); // zrender.js /** * ZRen ...
- Android Lint——内嵌于Android Studio的代码优化工具
Android Lint工具是Android Studio 自带的静态代码工模具,Android Lint是专门针对Android 定制的检查规则,因此可以检查出很多Android特有的代码缺陷.建议 ...