虽然题目不难,但是这应该是我第一次在考场上成功拿到计数题的不算低的分数,值得记录

如果对序列处理出$i$后面第一个比它大的位置$r_i$,那么两个序列同构的条件就是$r_i$都相同,而$r_i$构成一棵树,考虑计数树的数量

更进一步,我们只需计数那些由$1\cdots n$的排列生成的深度$\leq m$的树,因为用$[1,m]$中的数不能生成深度$\gt m$的树,生成这样的树的排列也可以通过恰当安排变成数字范围为$[1,m]$的序列

于是可以DP,设$f_{i,j}$表示深度$\leq i$,节点数为$j$的树的数量,枚举$j$在排列中的位置,有$f_{i,0}=1,f_{i,j}=\sum\limits_{k=0}^{j-1}f_{i-1,k}f_{i,j-1-k}$

设$f_{i,0\cdots n}$的生成函数为$F_i$,有$F_0=1,F_i=\frac1{1-xF_{i-1}}$

考场上就做到这里,$O(n^2\log n)$可以拿$70$分

$F_i$可以表示为$\frac{a_i}{b_i}$的形式,其中$a_i,b_i$都是$i$次多项式,推一下就可以矩阵快速幂

直接做显然不行,但因为是线性变换所以先DFT,对点值矩阵快速幂后IDFT回去即可

总时间复杂度$O(n\log n)$

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=998244353;
int mul(int a,int b){return(ll)a*b%mod;}
int ad(int a,int b){return(a+=b)>=mod?a-mod:a;}
int de(int a,int b){return(a-=b)<0?a+mod:a;}
int pow(int a,int b){
	int s=1;
	while(b){
		if(b&1)s=mul(s,a);
		a=mul(a,a);
		b>>=1;
	}
	return s;
}
int rev[262144],N,iN;
void pre(int n){
	int i,k=0;
	for(N=1,k=0;N<n;N<<=1)k++;
	for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
	iN=pow(N,mod-2);
}
void ntt(int*a,int on){
	int i,j,k,t,w,wn;
	for(i=0;i<N;i++){
		if(i<rev[i])swap(a[i],a[rev[i]]);
	}
	for(i=2;i<=N;i<<=1){
		wn=pow(3,on==1?(mod-1)/i:mod-1-(mod-1)/i);
		for(j=0;j<N;j+=i){
			w=1;
			for(k=0;k<i>>1;k++){
				t=mul(a[i/2+j+k],w);
				a[i/2+j+k]=de(a[j+k],t);
				a[j+k]=ad(a[j+k],t);
				w=mul(w,wn);
			}
		}
	}
	if(on==-1){
		for(i=0;i<N;i++)a[i]=mul(a[i],iN);
	}
}
int t1[262144];
void getinv(int*a,int*b,int n){
	if(n==1){
		b[0]=1;
		return;
	}
	getinv(a,b,n>>1);
	pre(n<<1);
	memset(t1,0,N<<2);
	memcpy(t1,a,n<<2);
	ntt(t1,1);
	ntt(b,1);
	for(int i=0;i<N;i++)b[i]=mul(b[i],de(2,mul(t1[i],b[i])));
	ntt(b,-1);
	memset(b+n,0,(N-n)<<2);
}
struct mat{
	int a[2][2];
	int*operator[](int k){return a[k];}
}t;
mat operator*(mat a,mat b){
	mat c;
	int i,j,k;
	ll t;
	for(i=0;i<2;i++){
		for(j=0;j<2;j++){
			t=0;
			for(k=0;k<2;k++)t+=(ll)a[i][k]*b[k][j];
			c[i][j]=t%mod;
		}
	}
	return c;
}
mat pow(mat a,int b){
	mat s;
	s[0][0]=s[1][1]=1;
	s[0][1]=s[1][0]=0;
	while(b){
		if(b&1)s=s*a;
		a=a*a;
		b>>=1;
	}
	return s;
}
int a[262144],b[262144],c[262144];
int main(){
	int n,m,i,k,wn,w;
	scanf("%d%d",&n,&m);
	if(m>n){
		printf("0");
		return 0;
	}
	for(k=1;k<=n;k<<=1);
	pre(k*2);
	wn=pow(3,(mod-1)/N);
	w=1;
	for(i=0;i<N;i++){
		t[0][0]=0;
		t[0][1]=mod-w;
		t[1][0]=t[1][1]=1;
		t=pow(t,m);
		a[i]=ad(t[0][0],t[1][0]);
		b[i]=ad(t[0][1],t[1][1]);
		w=mul(w,wn);
	}
	ntt(b,-1);
	getinv(b,c,k);
	ntt(c,1);
	for(i=0;i<N;i++)a[i]=mul(a[i],c[i]);
	ntt(a,-1);
	printf("%d",a[n]);
}

[UOJ424]count的更多相关文章

  1. [2018集训队作业][UOJ424] count [笛卡尔树+括号序列+折线法+组合数学]

    题面 请务必不要吐槽我的标签 传送门 思路 一个很重要的结论:原序列的一组同构的解等价于同一棵拥有$n$个节点的笛卡尔树 注意笛卡尔树的定义:父亲节点是区间最值,并且分割区间为左右部分 所以如果两个序 ...

  2. UOJ424 Count 生成函数、多项式求逆、矩阵快速幂

    传送门 两个序列相同当且仅当它们的笛卡尔树相同,于是变成笛卡尔树计数. 然后注意到每一个点的权值一定会比其左儿子的权值大,所以笛卡尔树上还不能够存在一条从根到某个节点的路径满足向左走的次数\(> ...

  3. nodejs api 中文文档

    文档首页 英文版文档 本作品采用知识共享署名-非商业性使用 3.0 未本地化版本许可协议进行许可. Node.js v0.10.18 手册 & 文档 索引 | 在单一页面中浏览 | JSON格 ...

  4. C#中Length和Count的区别(个人观点)

    这篇文章将会很短...短到比你的JJ还短,当然开玩笑了.网上有说过Length和count的区别,都是很含糊的,我没有发现有 文章说得比较透彻的,所以,虽然这篇文章很短,我还是希望能留在首页,听听大家 ...

  5. [PHP源码阅读]count函数

    在PHP编程中,在遍历数组的时候经常需要先计算数组的长度作为循环结束的判断条件,而在PHP里面对数组的操作是很频繁的,因此count也算是一个常用函数,下面研究一下count函数的具体实现. 我在gi ...

  6. EntityFramework.Extended 实现 update count+=1

    在使用 EF 的时候,EntityFramework.Extended 的作用:使IQueryable<T>转换为update table set ...,这样使我们在修改实体对象的时候, ...

  7. 学习笔记 MYSQL报错注入(count()、rand()、group by)

    首先看下常见的攻击载荷,如下: select count(*),(floor(rand(0)*2))x from table group by x; 然后对于攻击载荷进行解释, floor(rand( ...

  8. count(*) 与count (字段名)的区别

    count(*) 查出来的是:结果集的总条数 count(字段名) 查出来的是: 结果集中'字段名'不为空的记录的总条数

  9. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

随机推荐

  1. 原生的js实现jsonp的跨域封装

    一.原理 jsonp是利用浏览器请求script文件时不受同源策略的限制而实现的,伪造一个script标签,将请求数据的url赋值给script的src属性,并将该标签添加到html中,浏览器会自动发 ...

  2. JavaScript入门--慕课网学习笔记

     JAVASCRIPT—(慕课网)入门篇 我们来看看如何写入JS代码?你只需一步操作,使用<script>标签在HTML网页中插入JavaScript代码.注意, <script&g ...

  3. Lucene7.1.0版本的索引创建与查询以及维护,包括新版本的一些新特性探索!

    一 吐槽 lucene版本更新实在太快了,往往旧版本都还没学会,新的就出来,而且每个版本改动都特别大,尤其是4.7,6,6,7.1.......ε=(´ο`*)))唉,但不可否认,新版本确实要比旧版本 ...

  4. Sort Colors I & II

    Given an array with n objects colored red, white or blue, sort them so that objects of the same colo ...

  5. Git 创建仓库【转】

    转自:http://www.runoob.com/git/git-create-repository.html Git 创建仓库 本章节我们将为大家介绍如何创建一个 Git 仓库. 你可以使用一个已经 ...

  6. Linux触摸屏驱动测试程序范例【转】

    转自:http://blog.sina.com.cn/s/blog_4b4b54da0102viyl.html 转载2015-05-09 16:28:27 标签:androiditlinux 触摸屏驱 ...

  7. jQuery插件之ajaxFileUpload(异步上传图片并实时显示,并解决onchange后ajaxFileUpload失效问题)

    参考学习: 第一篇:http://www.cnblogs.com/kissdodog/archive/2012/12/15/2819025.html 第二篇:http://www.jb51.net/a ...

  8. 09 Command Documentation 命令文档

    Command Documentation 命令文档   There is a suite of programs to build and process Go source code. Inste ...

  9. 数据库-mysql数据连接

    一:Mysql 连接的使用 在前几章节中,我们已经学会了如果在一张表中读取数据,这是相对简单的,但是在真正的应用中经常需要从多个数据表中读取数据. 本章节我们将向大家介绍如何使用 MySQL 的 JO ...

  10. phpStudy配置https

    phpStudy配置https 1.打开vhosts-conf配置文件 2.在配置文件中增加如下内容 server { listen 443; server_name tam.gogugong.com ...