HDU 5322 Hope

考虑 $ dp[n] $ 表示 长度为 $ n $ 的所有排列的答案。

首先,对于一个排列来说,如果最大值在 $ i $ 位置,那么前 $ i - 1 $ 个数必然与 $ i $ 在一个联通块,且必然不会与 $ i $ 后面的数字在一个连通块。

那么考虑一种常用的排列的处理技巧,考虑将 $ n $ 插入 $ 1 \dots n-1 $ 的一个排列,比如插入的位置是 $ i $ 那么 $ i + 1 \dots n $ 相当于又是一个排列,而 $ 1 \dots i - 1 $ 的方案数是 $ A_{n-1}^{i-1} $ 所以答案就是

$ dp[n] = \displaystyle \sum_{i=1}^n A_{n-1}^{i-1} i^2 dp[n - i] $

这个式子看起来就很分治FFT。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
#define P 998244353
#define MAXN (1 << 19) + 12
int n;
int a[MAXN];
int Pow(int x,int y) {
int res=1;
while(y) {
if(y&1) res=res*(ll)x%P;
x=x*(ll)x%P,y>>=1;
}
return res;
}
int wn[2][MAXN];
void getwn(int l) {
for(int i=1;i<(1<<l);i<<=1) {
int w0=Pow(3,(P-1)/(i<<1)),w1=Pow(3,P-1-(P-1)/(i<<1));
wn[0][i]=wn[1][i]=1;
for(int j=1;j<i;++j)
wn[0][i+j]=wn[0][i+j-1]*(ll)w0%P,
wn[1][i+j]=wn[1][i+j-1]*(ll)w1%P;
}
}
int rev[MAXN];
void getr(int l) { for(int i=1;i<(1<<l);++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<l-1); }
void NTT(int *A,int len,int f) {
for(int i=0;i<len;++i) if(rev[i]<i) swap(A[i],A[rev[i]]);
for(int l=1;l<len;l<<=1)
for(int i=0;i<len;i+=(l<<1))
for(int k=0;k<l;++k) {
int t1=A[i+k],t2=A[i+l+k]*(ll)wn[f][l+k]%P;
A[i+k]=(t1+t2)%P;
A[i+l+k]=(t1-t2+P)%P;
}
if( f == 1 ) for(int inv=Pow(len,P-2),i=0;i<len;++i) A[i]=A[i]*(ll)inv%P;
}
int f[MAXN];
int A[MAXN] , B[MAXN];
int J[MAXN] , invJ[MAXN];
void CDQ(int *a,int *b,int l,int r){
if( l == r ) return;
int m = l + r >> 1;
CDQ( a , b , l , m );
int p = 1 , len = 0;
while( p <= ( r - l + 1 ) * 2 ) p <<= 1 , ++ len;
getr( len ) , getwn( len );
for( int i = 0 ; i < p ; ++i ) A[i] = B[i] = 0;
for( int i = l ; i <= m ; ++i ) A[i - l] = 1ll * a[i] * invJ[i] % P;
for( int i = 0 ; i <= r - l ; ++i ) B[i] = 1ll * i * i % P;
NTT( A , p , 0 ) , NTT( B , p , 0 );
for( int i = 0 ; i < p ; ++i ) A[i] = 1ll * A[i] * B[i] % P;
NTT( A , p , 1 );
for( int i = m + 1 ; i <= r ; ++i ) a[i] = ( a[i] + 1ll * J[i - 1] * A[i-l] % P ) % P;
CDQ( a , b , m + 1 , r );
}
int main() {
J[0] = invJ[0] = 1;
for( int i = 1 ; i < MAXN ; ++ i ) J[i] = 1ll * J[i - 1] * i % P , invJ[i] = Pow( J[i] , P - 2 );
f[0] = 1;
CDQ( f , a , 0 , 100006 );
int x;
while( cin >> x ) printf("%d\n",f[x]);
}

HDU 5322 Hope的更多相关文章

  1. HDU 5322 Hope ——NTT 分治 递推

    发现可以推出递推式.(并不会) 然后化简一下,稍有常识的人都能看出这是一个NTT+分治的情况. 然而还有更巧妙的方法,直接化简一下递推就可以了. 太过巧妙,此处不表,建议大家找到那篇博客. 自行抄写 ...

  2. HDU 5322 Hope (分治NTT优化DP)

    题面传送门 题目大意: 假设现在有一个排列,每个数和在它右面第一个比它大的数连一条无向边,会形成很多联通块. 定义一个联通块的权值为:联通块内元素数量的平方. 定义一个排列的权值为:每个联通块的权值之 ...

  3. HDU 5319 Painter(枚举)

    Painter Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Su ...

  4. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  5. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  6. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  7. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  8. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  9. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

随机推荐

  1. 【UE4 设计模式】策略模式 Strategy Pattern

    概述 描述 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法的变化不会影响到使用算法的客户. 套路 Context(环境类) 负责使用算法策略,其中维持了一 ...

  2. Scrum Meeting 0529

    零.说明 日期:2021-5-29 任务:简要汇报七日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 七日内已完成的任务 后两日计划完成的任务 困难 qsy PM&前端 完成后端管 ...

  3. [no code][scrum meeting] Beta 2

    例会时间:5月14日11:30,主持者:乔玺华 下次例会时间:5月15日11:30,主持者:肖思炀 一.工作汇报 人员 昨日完成任务 明日要完成的任务 乔玺华 - 开issue,分配时间 黎正宇 - ...

  4. 2021.9.9考试总结[NOIP模拟50]

    T1 第零题 神秘结论:从一个点满体力到另一个点的复活次数与倒过来相同. 于是预处理出每个点向上走第$2^i$个死亡点的位置,具体实现可以倍增或二分. 每次询问先从两个点同时向上倍增,都转到离$LCA ...

  5. C/C++如何传递二维数组?

    用二维数组作为参数传递(用二维数组处理矩阵),但是希望接受传递二维数组参数的函数可以处理任意维度的数组(希望矩阵的行数和列数都是不固定的). ----------------------------- ...

  6. ARM 链接配置.lds文件学习<转>

    本文由Jacky原创,来自http://blog.chinaunix.net/u1/58780/showart.php?id=462971 对于.lds文件,它定义了整个程序编译之后的连接过程,决定了 ...

  7. 痞子衡嵌入式:借助Serial Plot软件测量i.MXRT系列FlexSPI驱动Flash页编程执行时间

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT系列FlexSPI驱动Flash页编程执行时间. 痞子衡之前写过一篇文章 <串行NOR Flash的页编程模式对于量产 ...

  8. 力扣 - 剑指 Offer 06. 从尾到头打印链表.md

    题目 剑指 Offer 06. 从尾到头打印链表 思路1(递归) 首先先遍历整个脸表,计算出链表的长度(用于初始化数组).然后进行递归,从链表头部递归到尾部,这期间什么都不做,直到递归到最后一个节点的 ...

  9. fiddler 手机+浏览器 抓包

    用fiddler对手机上的程序进行抓包   前提: 1.必须确保安装fiddler的电脑和手机在同一个wifi环境下 备注:如果电脑用的是台式机,可以安装一个随身wifi,来确保台式机和手机在同一wi ...

  10. 2021 羊城杯WriteUP

    比赛感受 题目质量挺不错的,不知道题目会不会上buu有机会复现一下,躺了个三等奖,发下队伍的wp Team BinX from GZHU web Checkin_Go 源码下载下来发现是go语言写的 ...