LOJ #6538. 烷基计数 加强版 加强版(生成函数,burnside引理,多项式牛顿迭代)
不妨设\(A(x)\)表示答案。
对于一个点,考虑它的三个子节点,直接卷起来是\(A(x)^3\),但是这样肯定会计重,因为我们要的是无序的子节点。
那么用burnside引理,枚举一个排列,一个环的选择要相同,如果环的大小是y,则对应\(A(x^y)\)。
最后可以得到:
\(A(x)=x{A(x)^3+3A(x^2)A(x)+2A(x^3)\over 6}+1\)
分治NTT可以解这个方程,不过因为有3次的,比较复杂,考虑用牛顿迭代:
\(F(A(x))=x{A(x)^3+3A(x^2)A(x)+2A(x^3)\over 6}+1-A(x)=0\)
\(new A(x)=A(x)-{F(A(x))\over F(A(x))'}\)
问题在于\(F(A(x))\)中有\(A(x^2)、A(x^3)、x\)这样的项,如何求导。
注意牛顿迭代的倍增中,已经求出了\(mod~x^{n/2}\)的答案,那么\(A(x^2)、A(x^3)、x\)是已知的,可以视作常数。
所以\(F(A(x))'=x{3A(x)^2 + 3A(x^2)\over 6} - 1\)。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i <  B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int mo = 998244353;
ll ksm(ll x, ll y) {
	ll s = 1;
	for(; y; y /= 2, x = x * x % mo)
		if(y & 1) s = s * x % mo;
	return s;
}
typedef vector<ll> V;
#define pb push_back
#define si size()
#define re resize
namespace ntt {
const int nm = 1 << 18;
int r[nm]; ll w[nm], a[nm];
void build() {
	for(int n = 1; n < nm; n *= 2) {
		ll v = ksm(3, (mo - 1) / 2 / n)	;
		w[n] = 1;
		ff(i, 1, n) w[n + i] = w[n + i - 1] * v % mo;
	}
}
void dft(V &c, int f) {
	int n = c.si;
	ff(i, 0, n) a[i] = c[i];
	ff(i, 0, n) {
		r[i] = r[i / 2] / 2 + (i & 1) * n / 2;
		if(i < r[i]) swap(a[i], a[r[i]]);
	} ll b;
	for(int i = 1; i < n; i *= 2) for(int j = 0; j < n; j += 2 * i) ff(k, 0, i)
		b = a[i + j + k] * w[i + k], a[i + j + k] = (a[j + k] - b) % mo, a[j + k] = (a[j + k] + b) % mo;
	if(f == -1) {
		reverse(a + 1, a + n);
		b = ksm(n, mo - 2);
		ff(i, 0, n) a[i] = (a[i] + mo) * b % mo;
	}
	ff(i, 0, n) c[i] = a[i];
}
}
using ntt :: dft;
V operator *(V a, V b) {
	int n0 = a.si + b.si - 1, n = 1;
	while(n < n0) n *= 2;
	a.re(n); b.re(n);
	dft(a, 1); dft(b, 1);
	ff(i, 0, n) a[i] = a[i] * b[i] % mo;
	dft(a, -1);
	a.re(n0); return a;
}
V operator +(V a, V b) {
	a.re(max(a.si, b.si));
	ff(i, 0, b.si) a[i] = (a[i] + b[i]) % mo;
	return a;
}
V operator -(V a, V b) {
	a.re(max(a.si, b.si));
	ff(i, 0, b.si) a[i] = (a[i] - b[i] + mo) % mo;
	return a;
}
V operator * (V a, int b) {
	ff(i, 0, a.si) a[i] = a[i] * b % mo;
	return a;
}
V qni(V a) {
	V b; b.resize(1); b[0] = ksm(a[0], mo - 2);
	for(int n = 2; n < a.si * 2; n *= 2) {
		V c = a; c.re(n); c.re(2 * n);
		V d = b; b.re(2 * n); d.re(n);
		dft(b, 1); dft(c, 1);
		ff(i, 0, b.si) b[i] = b[i] * b[i] % mo * c[i] % mo;
		dft(b, -1); b.re(n);
		ff(i, 0, n) b[i] = (2 * d[i] - b[i] + mo) % mo;
	}
	b.re(a.si); return b;
}
V yy(V a) {
	a.insert(a.begin(), 0);
	return a;
}
V stay(V a, int y, int n) {
	V b; b.resize(n);
	int mx = a.si - 1; mx = min(mx, (n - 1) / y);
	fo(i, 0, mx) b[i * y] = a[i];
	return b;
}
const ll ni6 = ksm(6, mo - 2);
V newton(int n0) {
	V b; b.re(1); b[0] = 1;
	for(int n = 2; n <= n0 * 2; n *= 2) {
		V c = b * b * b + stay(b, 2, n) * b * 3 + stay(b, 3, n) * 2;
		c = yy(c * ni6); c.re(n);
		c[0] ++; c = c - b;
		V d = b * b * 3 + stay(b, 2, n) * 3;
		d = yy(d * ni6); d[0] --; d.re(n);
		b = b - c * qni(d); b.re(n);
	}
	return b;
}
int n;
int main() {
	ntt :: build();
	scanf("%d", &n);
	V a = newton(n);
	pp("%lld\n", a[n]);
}
												
											LOJ #6538. 烷基计数 加强版 加强版(生成函数,burnside引理,多项式牛顿迭代)的更多相关文章
- 【loj6538】烷基计数 加强版 加强版 Burnside引理+多项式牛顿迭代
		
别问我为啥突然刷了道OI题,也别问我为啥花括号不换行了... 题目描述 求含 $n$ 个碳原子的本质不同的烷基数目模 $998244353$ 的结果.$1\le n\le 10^5$ . 题解 Bur ...
 - [LOJ 6185]烷基计数
		
Description 众所周知,大连 24 中是一所神奇的学校,在那里,化竞的同学很多都擅长写代码. 有一天,化学不及格的胡小兔向化竞巨佬晴岚请教化学题: “n 个碳原子的烷基共有多少种同分异构体? ...
 - 等价类计数(Polya定理/Burnside引理)学习笔记
		
参考:刘汝佳<算法竞赛入门经典训练指南> 感觉是非常远古的东西了,几乎从来没有看到过需要用这个的题,还是学一发以防翻车. 置换:排列的一一映射.置换乘法相当于函数复合.满足结合律,不满足交 ...
 - BZOJ5119 生成树计数(prufer+生成函数+分治FFT+多项式exp)
		
https://www.luogu.org/problemnew/solution/P4002 神树的题解写的很清楚了.稍微补充: 1.[x^i]ln(A(ax))=a^i[x^i]ln(A(x)), ...
 - 洛谷 P4708 - 画画(Burnside 引理+组合数学)
		
洛谷题面传送门 神仙题 %%%%%%%%%%%%%%%%%%%% 题解搬运人来了 首先看到本质不同(无标号)的图计数咱们可以想到 Burnside 引理,具体来说,我们枚举一个排列 \(p\),并统计 ...
 - Luogu P5564 [Celeste-B]Say Goodbye (多项式、FFT、Burnside引理、组合计数)
		
题目链接 https://www.luogu.org/problem/P5564 题解 这题最重要的一步是读明白题. 为了方便起见下面设环长可以是\(1\), 最后统计答案时去掉即可. 实际上就相当于 ...
 - 【等价的穿越】Burnside引理&Pólya计数法
		
Problem 起源: SGU 294 He's Circle 遗憾的是,被吃了. Poj有道类似的: Mission 一个长度为n(1≤n≤24)的环由0,1,2组成,求有多少本质不同的环. 实际上 ...
 - 等价类计数:Burnside引理 & Polya定理
		
提示: 本文并非严谨的数学分析,有很多地方是自己瞎口胡的,仅供参考.有错误请不吝指出 :p 1. 群 1.1 群的概念 群 \((S,\circ)\) 是一个元素集合 \(S\) 和一种二元运算 $ ...
 - BZOJ 1488 Luogu P4727 [HNOI2009]图的同构 (Burnside引理、组合计数)
		
题目链接 (Luogu) https://www.luogu.org/problem/P4727 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.ph ...
 
随机推荐
- 解决vue项目打包之后出现源代码的问题
			
config/index.js 页面找到productionSourceMap:ture 改为 productionSourceMap:false
 - androidstudio 2.3.3 jni过程汇总(1):1、自己编写c文件并使用(原)
			
1.编写java代码,指定lib和native方法.package com.taven.myapplication; package com.taven.myapplication; import a ...
 - ajax请求的原生js实现
			
我们使用ajax请求一般都用的jQuery, axios封装好了的api, 那么如果只能用原生js, 我们该如何操作了? 上代码. 我们在同目录下写好一个json文件(data.json)用于请求测试 ...
 - rest framework之过滤组件
			
一.普通过滤 (一)get_queryset get_queryset方法是GenericAPIView提供的一个方法,旨在返回queryset数据集,而过滤就是要在这个方法返回数据集之前对数据进行筛 ...
 - Java数据库事务四大特性以及隔离级别
			
四大特性ACID 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚.失败回滚的操作事务,将不能对数据库有任何影响 一致性(Consistency) 一致性是指事 ...
 - leetcood学习笔记-7
			
Python join()方法 join()方法语法: str.join(sequence) 参数 sequence -- 要连接的元素序列. 返回值 返回通过指定字符连接序列中元素后生成的新字符串. ...
 - 一个类似indexOf()的功能的函数
			
之前面试的时候遇到了这样的一道题,不过写的时候有些细节没注意到,现在重新写了一下. 写一个类似indexOf()的功能的函数 var str = "dafdfgvdahjfbhyuyvtur ...
 - centos7 安装telent和telnet-server
			
安装centos7 无telnet命令 先检查CentOS7.0是否已经安装以下两个安装包:telnet-server.xinetd.命令如下: rpm -q telnet-server rpm -q ...
 - Openfire部署(一)
			
1.从官网下载openfire_4_1_4.tar.gz文件: 2.上传到linux上,解压缩 3.启动openfire [root@localhost opt]# cd openfire/bin [ ...
 - delphi基础篇之数据类型之二:2.字符串类型
			
2.字符串类型 2.1.ShortStringShortString 又称为短字符串(相对的,Ansistring.widestring.unicodestring 称为长字符串),其实质上是一个编译 ...