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

如果对序列处理出$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. 【codeforces】【比赛题解】#868 CF Round #438 (Div.1+Div.2)

    这次是Div.1+Div.2,所以有7题. 因为时间较早,而且正好赶上训练,所以机房开黑做. 然而我们都只做了3题.:(. 链接. [A]声控解锁 题意: Arkady的宠物狗Mu-mu有一只手机.它 ...

  2. DirectFB简介以及移植[一]【转】

    转自:https://blog.csdn.net/wavemcu/article/details/39251805 ****************************************** ...

  3. 编译安装 zbar 时两次 make 带来的惊喜

    为了装 php 的条形码扩展模块 php-zbarcode,先装了一天的 ImageMagick 和 zbar.也许和我装的 Ubuntu 17.10 的有版本兼容问题吧,总之什么毛病都有,apt 不 ...

  4. Serv-U 的升级及数据备份和迁移【转】

    Serv-U 配置备份   在serv-u7.x及以上版本安装目录下,有一个文件Serv-U.Archive是serv-u的配置文件,有一个users文件夹是Serv-U的域和用户的信息,那么我们只需 ...

  5. 数据库-python操作mysql(pymsql)

    pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同 一:安装pymysql pip3 install pymysql 二:使用pytmysql # -*- codin ...

  6. sql server 2000系统表sysproperties在SQL 2008中无效的问题

    Sqlserver有一个扩展属性系统表sysproperties,因为只接触过MSSQL2005及以后的版本,在生产库2008版本及联机文档上搜了下都找不到这个系统表,后来发现这个系统表在2005版本 ...

  7. Radon变换——MATLAB

    算法说明: 图像的Radon变换是每个像素的Radon变换的总和. 该算法首先将图像中的像素分成四个子像素,并分别投影每个子像素,如下图所示. 根据投影位置和箱体中心之间的距离,每个子像素的贡献按比例 ...

  8. C#基础之数据类型

    c#有15个预定义类型,其中13个是值类型,两个是引用类型(string 和 object) 1.整型 2.浮点类型 float数据类型用于较小的浮点数,因为它要求的精度较低. double数据类型比 ...

  9. Jenkins+Docker持续集成

    本节内容: Jenkins介绍 安装部署Jenkins Jenkins构建maven风格的job Jenkins邮件通知设置 Sonar Jenkins与Docker结合 一.Jenkins介绍 Je ...

  10. MFC+WinPcap编写一个嗅探器之六(分析模块)

    这一节是程序的核心,也是最复杂的地方 首先需要明白的一点是,一般对于一个有界面的程序来说,往往需要多线程.本程序中除了界面线程外,抓包需要另外创建一个新的线程.在写抓包函数之前,首先要将前面两个模块的 ...