题面

一根长为 n 的无色纸条,每个位置依次编号为 1,2,3,…,n ,m 次操作,第 i 次操作把纸条的一段区间 [l,r] (l <= r , l,r ∈ {1,2,3,…,n})涂成颜色 i ,最后一定要把纸条涂满颜色,问最终的纸条有多少种可能的模样。

输入为两个数 n,m ,输出为你的答案

m <= n <= 1e6

题解

不考虑先前染的颜色被覆盖这件事情。如果某种颜色在最终的序列中出现了 x 次,那么我们就直接认为在染这种颜色的时候,我们只染了 x 个格子。
但这样一来每次染色的格子就不再是连续的一段了。不过如果我们把给一段格子染色认为是在已被染色的颜色序列中插入一段,那么一切都显得简单而明晰了!

首先我们可以想到一个 DP,

d

p

[

i

]

[

j

]

dp[i][j]

dp[i][j] 表示纸条长度为 j,强制最后出现 i 种颜色时,这 i 种颜色的方案数(也就是说先不乘

C

(

m

,

i

)

C(m,i)

C(m,i) 之类的),那么有如下转移:

d

p

[

i

]

[

j

]

(

j

+

1

)
  


  

d

p

[

i

+

1

]

[

k

]

k

>

j

dp[i][j]\cdot (j+1)\;\rightarrow\;dp[i+1][k](k>j)

dp[i][j]⋅(j+1)→dp[i+1][k](k>j)

(可以看作是在格子间隙中插入了一段颜色为 i+1 的)

我们最后要求的是

i

=

1

m

d

p

[

i

]

[

n

]

C

(

m

1

,

i

1

)

\sum_{i=1}^{m}dp[i][n]*C(m-1,i-1)

∑i=1m​dp[i][n]∗C(m−1,i−1) 因为最后一种颜色必须出现所以是

C

(

m

1

,

i

1

)

C(m-1,i-1)

C(m−1,i−1)。

用前缀和优化可以做到 n 方,接下来我们想想怎么优化。

化式子无比艰难,我们不如感性分析一下。看上方的转移,从

d

p

[

0

]

[

0

]

dp[0][0]

dp[0][0] 转移过来,我们首先选了一个数 k > 0 转移到了

d

p

[

1

]

[

k

]

dp[1][k]

dp[1][k],然后还可以再选一个数 k’ > k 来转移到

d

p

[

2

]

[

k

]

dp[2][k']

dp[2][k′],此时的贡献为

(

k

+

1

)

(k+1)

(k+1),于是再选个数 k’’ > k’,对

d

p

[

3

]

[

k

]

dp[3][k'']

dp[3][k′′] 产生

(

k

+

1

)

(

k

+

1

)

(k+1)(k'+1)

(k+1)(k′+1) 的贡献…… 对于

d

p

[

i

]

[

n

]

dp[i][n]

dp[i][n] 来说,相当于我们在

[

1

,

n

1

]

[1,n-1]

[1,n−1] 中选了

i

1

i-1

i−1 个数,把它们都+1,然后乘起来,这样的所有方案的乘积和。

所以,

d

p

[

i

]

[

n

]

dp[i][n]

dp[i][n] 就等于

F

n

1

=

i

=

1

n

1

(

x

+

(

i

+

1

)

)

F_{n-1}=\prod_{i=1}^{n-1}(x+(i+1))

Fn−1​=∏i=1n−1​(x+(i+1)) 这个多项式的

n

i

n - i

n−i 次项,这里稍微转化理解一下,不难明白,相当于不选产生 1 的贡献,选产生 i+1 的贡献,k 次项系数表示 k 个数不选。

于是可以分治 NTT 做,求出这个多项式,

O

(

n

log

2

n

)

O(n\log^2n)

O(nlog2n),很可惜还是过不了。

实际上我们乘的这 n-1 个多项式是有规律的,我们可以推一推。

假设我们已经求出了

F

t

F_t

Ft​ ,我们要求

F

2

t

F_{2t}

F2t​ ,有这个式子:

F

2

t

=

i

=

1

2

t

(

x

+

i

+

1

)

=

i

=

1

t

(

x

+

i

+

1

)

i

=

1

t

(

x

+

(

i

+

t

)

+

1

)

=

F

t

i

=

1

t

(

x

+

(

i

+

t

)

+

1

)

F_{2t}=\prod_{i=1}^{2t}(x+i+1)=\prod_{i=1}^{t}(x+i+1)\prod_{i=1}^{t}(x+(i+t)+1)\\ =F_t\prod_{i=1}^{t}(x+(i+t)+1)

F2t​=∏i=12t​(x+i+1)=∏i=1t​(x+i+1)∏i=1t​(x+(i+t)+1)=Ft​∏i=1t​(x+(i+t)+1)

不妨就设右边那坨为

F

t

F_t'

Ft′​,那么

F

2

t

=

F

t

F

t

F_{2t}=F_t\cdot F_{t}'

F2t​=Ft​⋅Ft′​ ,我们知道

F

t

F_t'

Ft′​ 的话就可以 NTT 了,现在来推

F

t

F_t'

Ft′​:

我们先令

X

=

x

+

t

X = x+t

X=x+t 来换个元,

F

t

=

i

=

1

t

(

x

+

i

+

t

+

1

)

=

i

=

1

t

(

(

x

+

t

)

+

i

+

1

)

=

i

=

1

t

(

X

+

i

+

1

)

F_t'=\prod_{i=1}^{t}(x+i+t+1)=\prod_{i=1}^{t}((x+t)+i+1)=\prod_{i=1}^{t}(X+i+1)

Ft′​=∏i=1t​(x+i+t+1)=∏i=1t​((x+t)+i+1)=∏i=1t​(X+i+1)

然后会发现它是跟

F

t

F_t

Ft​ 一样的形式,我们把

F

t

F_t

Ft​ 的每项系数带入:

F

t

=

i

=

0

t

F

t

[

i

]

X

i

=

i

=

0

t

F

t

[

i

]

(

x

+

t

)

i

F_t'=\sum_{i=0}^{t}F_t[i]X^i=\sum_{i=0}^{t}F_t[i](x+t)^i

Ft′​=∑i=0t​Ft​[i]Xi=∑i=0t​Ft​[i](x+t)i

利用二项式定理变成这样:

i

=

0

t

F

t

[

i

]

j

=

0

i

x

j

t

i

j

C

(

i

,

j

)

\sum_{i=0}^{t}F_t[i]\sum_{j=0}^{i}x^jt^{i-j}C(i,j)

∑i=0t​Ft​[i]∑j=0i​xjti−jC(i,j)

换个枚举顺序:

j

=

0

t

x

j

i

=

j

t

F

t

[

i

]

t

i

j

C

(

i

,

j

)

\sum_{j=0}^{t}x^j\sum_{i=j}^{t}F_t[i]t^{i-j}C(i,j)

∑j=0t​xj∑i=jt​Ft​[i]ti−jC(i,j)

我们令

B

[

i

]

=

F

t

[

t

i

]

B[i]=F_t[t-i]

B[i]=Ft​[t−i] 翻转一下:

j

=

0

t

x

j

i

=

j

t

B

[

t

i

]

t

i

j

C

(

i

,

j

)

\sum_{j=0}^{t}x^j\sum_{i=j}^{t}B[t-i]t^{i-j}C(i,j)

∑j=0t​xj∑i=jt​B[t−i]ti−jC(i,j)

j

=

0

t

x

j

i

=

j

t

B

[

t

i

]

t

i

j

i

!

j

!

(

i

j

!

)

\rightarrow\sum_{j=0}^{t}x^j\sum_{i=j}^{t}B[t-i]t^{i-j}\frac{i!}{j!(i-j!)}

→∑j=0t​xj∑i=jt​B[t−i]ti−jj!(i−j!)i!​

右边就变成了一个卷积的形式,最终这样应该更好理解:

F

t

=

j

=

0

t

(

1

j

!

(

i

=

j

t

B

[

t

i

]

t

i

j

i

!

(

i

j

)

!

)

)

x

j

F_t'=\sum_{j=0}^{t}\left(\frac{1}{j!}\cdot(\sum_{i=j}^{t}B[t-i]t^{i-j}\frac{i!}{(i-j)!})\right)\cdot x^{j}

Ft′​=∑j=0t​(j!1​⋅(∑i=jt​B[t−i]ti−j(i−j)!i!​))⋅xj

求出它之后我们就可以求出

F

2

t

F_{2t}

F2t​ 了,这样递归,复杂度

T

(

n

)

=

T

(

n

2

)

+

O

(

n

log

n

)

=

O

(

n

log

n

)

T(n)=T(\frac{n}{2})+O(n\log n)=O(n\log n)

T(n)=T(2n​)+O(nlogn)=O(nlogn) ,可以过。

CODE

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 1000005
#define DB double
#define LL long long
#define ENDL putchar('\n')
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return x*f;
}
const int MOD = 998244353;
const int proot = 3;
int n,m,i,j,s,o,k;
int dp[MAXN];
int fac[MAXN],inv[MAXN],invf[MAXN];
int C(int n,int m) {
if(m > n || n < 0) return 0;
return fac[n] *1ll* invf[n-m] % MOD *1ll* invf[m] % MOD;
}
int xm[MAXN<<2],rev[MAXN<<2],om;
int qkpow(int a,int b) {
int res = 1;
while(b > 0) {
if(b & 1) res = res *1ll* a % MOD;
a = a *1ll* a % MOD; b >>= 1;
}return res;
}
void NTT(int *s,int n,int op) {
for(int i = 1;i < n;i ++) {
rev[i] = ((rev[i>>1]>>1) | ((i & 1) ? (n>>1):0));
if(rev[i] < i) swap(s[rev[i]],s[i]);
}
om = qkpow(proot,(MOD-1)/n); xm[0] = 1;
if(op<0) om = qkpow(om,MOD-2);
for(int i = 1;i <= n;i ++) xm[i] = xm[i-1] *1ll* om % MOD;
for(int k = 2,t = (n>>1);k <= n;k <<= 1,t >>= 1) {
for(int j = 0;j < n;j += k) {
for(int i = j,l=0;i < j+(k>>1);i ++,l += t) {
int A = s[i],B = s[i+(k>>1)];
s[i] = (A + xm[l] *1ll* B % MOD) % MOD;
s[i+(k>>1)] = (A +MOD- xm[l] *1ll* B % MOD) % MOD;
}
}
}
int invn = qkpow(n,MOD-2);
if(op < 0) for(int i = 0;i < n;i ++) s[i] = s[i] *1ll* invn % MOD;
return ;
}
int A[MAXN<<2],B[MAXN<<2],cc[MAXN<<2];
void solve(int n) {
if(n == 1) {
A[0] = 2;A[1] = 1;return ;
}
int md = n>>1;
solve(md);
int po = 1,le = 1;
while(le <= md*2) le <<= 1;
for(int i = 0;i <= md;i ++) {
B[i] = A[md-i] *1ll* fac[md-i] % MOD;
cc[i] = po *1ll* invf[i] % MOD;
po = po *1ll* md % MOD;
}
NTT(B,le,1);NTT(cc,le,1);
for(int i = 0;i <= le;i ++) B[i] = B[i] *1ll* cc[i] % MOD,cc[i] = 0;
NTT(B,le,-1);
for(int i = md+1;i <= le;i ++) B[i] = 0;
for(int i = 0;i <= md;i ++) B[i] = B[i] *1ll* invf[md-i] % MOD;
for(int i = 0;i+i <= md;i ++) swap(B[i],B[md-i]);
while(le <= n) le <<= 1;
NTT(B,le,1); NTT(A,le,1);
for(int i = 0;i <= le;i ++) A[i] = A[i] *1ll* B[i] % MOD,B[i] = 0;
NTT(A,le,-1); for(int i = n+1;i <= le;i ++) A[i] = 0;
if(n & 1) {
for(int i = n;i > 0;i --) {
A[i] = (A[i] *1ll* (n+1) % MOD + A[i-1]) % MOD;
}
A[0] = A[0] *1ll* (n+1) % MOD;
}
return ;
}
int main() {
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
n = read();m = read();
fac[0] = fac[1] = inv[0] = inv[1] = invf[0] = invf[1] = 1;
for(int i = 2;i <= max(n,m);i ++) {
fac[i] = fac[i-1] *1ll* i % MOD;
inv[i] = (MOD-inv[MOD % i]) *1ll* (MOD/i) % MOD;
invf[i] = invf[i-1] *1ll* inv[i] % MOD;
}
solve(n-1);
int ans = 0;
for(int i = 1;i <= min(n,m);i ++) {
(ans += A[n-i] *1ll* C(m-1,i-1) % MOD) %= MOD;
}
printf("%d",ans);
return 0;
}

NOI 2019 省选模拟赛 T1【JZOJ6082】 染色问题(color) (多项式,数论优化)的更多相关文章

  1. [NOI.AC省选模拟赛3.23] 染色 [点分治+BFS序]

    题面 传送门 重要思想 真的是没想到,我很久以来一直以为总会有应用的$BFS$序,最终居然是以这种方式出现在题目中 笔记:$BFS$序可以用来处理限制点对距离的题目(综合点分树使用) 思路 本题中首先 ...

  2. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  3. NOI.AC省选模拟赛第一场 T1 (树上高斯消元)

    link 很容易对于每个点列出式子 \(f_{x,y}=(f_{x,y-1}+f_{x,y}+f_{x,y+1}+f_{x+1,y})/4\)(边角转移类似,略) 这个转移是相互依赖的就gg了 不过你 ...

  4. 2019.2.25 模拟赛T1【集训队作业2018】小Z的礼物

    T1: [集训队作业2018]小Z的礼物 我们发现我们要求的是覆盖所有集合里的元素的期望时间. 设\(t_{i,j}\)表示第一次覆盖第i行第j列的格子的时间,我们要求的是\(max\{ALL\}\) ...

  5. [NOI.AC省选模拟赛3.31] 附耳而至 [平面图+最小割]

    题面 传送门 思路 其实就是很明显的平面图模型. 不咕咕咕的平面图学习笔记 用最左转线求出对偶图的点,以及原图中每个边两侧的点是谁 建立网络流图: 源点连接至每一个对偶图点,权值为这个区域的光明能量 ...

  6. [NOI.AC省选模拟赛3.23] 集合 [数学]

    题面 传送门 一句话题意: 给定$n\leq 1e9,k\leq 1e7,T\leq 1e9$ 设全集$U=\lbrace 1,2,3,...n\rbrace $,求$(min_{x\in S}\lb ...

  7. [noi.ac省选模拟赛]第12场题解集合

    题目 比赛界面. T1 数据范围明示直接\(O(n^2)\)计算,问题就在如何快速计算. 树上路径统计通常会用到差分方法.这里有两棵树,因此我们可以做"差分套差分",在 A 树上对 ...

  8. [noi.ac省选模拟赛]第10场题解集合

    题目 比赛界面. T1 不难想到,对于一个与\(k\)根棍子连接的轨道,我们可以将它拆分成\(k+1\)个点,表示这条轨道不同的\(k+1\)段. 那么,棍子就成为了点与点之间的边.可以发现,按照棍子 ...

  9. [noi.ac省选模拟赛]第11场题解集合

    题目   比赛界面. T1   比较简单.容易想到是求鱼竿的最大独立集.由于题目的鱼竿可以被分割为二分图,就可以想到最大匹配.   尝试建边之后会发现边的数量不小,但联系题目性质会发现对于一条鱼竿,它 ...

随机推荐

  1. mysql数据恢复 根据旧备份的sql文件和当前data下的ibd文件恢复innodb引擎数据

    1.使用navicat fro mysql数据库工具进行恢复 2.将原有备份的sql文件导入数据库 3.新建一个空数据库 4将备份数据库的数据表复制到新建数据库(只复制表格式) 5.在命令行模式中 u ...

  2. 浅析Kubernetes架构之workqueue

    通用队列 在kubernetes中,使用go的channel无法满足kubernetes的应用场景,如延迟.限速等:在kubernetes中存在三种队列通用队列 common queue ,延迟队列 ...

  3. 在公网服务器搭建CobaltStrike4.0

    因为工作需要使用cs,正好之前腾讯云薅了一把羊毛,就把VPS装起来cs. 选的环境是centos7.6 cs运行需要java环境 先使用yum -y list java* 查看yum存在的java库 ...

  4. 自定义监控lvs

    1. 修改zabbix_agent配置文件添加以下内容,重启agent Include=/etc/zabbix/zabbix_agentd.d/ 2. 在zabbix安装目录下的scripts目录下添 ...

  5. CompletableFuture的入门

    runAsync 和 supplyAsync runAsync接受一个Runable的实现,无返回值 CompletableFuture.runAsync(()->System.out.prin ...

  6. Lua5.4源码剖析:二. 详解String数据结构及操作算法

    概述 lua字符串通过操作算法和内存管理,有以下优点: 节省内存. 字符串比较效率高.(比较哈希值) 问题: 相同的字符串共享同一份内存么? 相同的长字符串一定不共享同一份内存么? lua字符串如何管 ...

  7. Contest

    Contest 题目 链接 题目描述 \(n\) 支队伍一共参加了三场比赛. 一支队伍 \(x\) 认为自己比另一支队伍 \(y\) 强当且仅当 \(x\) 在至少一场比赛中比 \(y\) 的排名高. ...

  8. Eclipse拷贝动态的web工程

    1.选中需要拷贝的工程,CTRL+C,然后CTRL+V 2.在web动态工程中,还需要选中新拷贝工程,右键选中properties,然后搜索web,--->Web Project Setttin ...

  9. 中国顶级程序员,从金山WPS走出来,自研了“表格编程”神器

    程序员的圈子里有很多如明星般闪耀的牛人! 有中国"第一代程序员"--求伯君,有在微信获得巨大成功的张小龙,有图灵奖获得者姚期智,有商业巨子张一鸣,更有开源影响力人物--章亦春. 章 ...

  10. Linux学习系列--用户(组)新增、查看和删除

    在实际的工作中,在接触Linux的用户组管理的时候,一般来说都是在系统开建设的时候设置好,root权限由特定的负责人保管用户密码,避免误操作带来不必要的麻烦. 在具体使用的时候,会利用相关的命令设置一 ...