[ACNOI2022]就我不会签到题

题目

题目背景
《咏 D D ( X Y X ) \sf DD(XYX) DD(XYX)

红石音乐是主题, O I \rm OI OI 易如小游戏。可怜凡人单线程,谁与校长争第一?

《咏 O U Y E \sf OUYE OUYE

润人装弱已毕业,深夜内卷未曾歇。待到今年 I O I \rm IOI IOI,金牌榜首是卷爷。

《咏 D D G \sf DDG DDG

卷毛狗,卷不忘磨牙。金牌德牧闪击战,欲成大业先结扎。再把人类杀。

《咏 Respectable   Brilliant   Queen \textsf{Respectable Brilliant Queen} Respectable Brilliant Queen

去年富贵今日贫,弃我不顾狗熊岭。无情最是公交车,只动身体不动心。

《咏 O n e I n D a r k \sf OneInDark OneInDark

三年苦学无实力,语文破烂难强基。皇天不与苍生便,常使 O I D \sf OID OID 泪满襟!

题目描述
对于长为 n n n 的排列 { a 1 , a 2 , … , a n } \{a_1,a_2,\dots,a_n\} {a1,a2,,an},若存在 k ∈ [ 1 , n ] k\in[1,n] k[1,n] 使得 { a 1 , a 2 , … , a k } \{a_1,a_2,\dots,a_k\} {a1,a2,,ak} 单调递减且 { a k , a k + 1 , … , a n } \{a_k,a_{k+1},\dots,a_n\} {ak,ak+1,,an} 单调递增,则 { a } \{a\} {a} 是 “淡淡谷的”( slight valley \text{slight valley} slight valley)。

称另一个长为 n n n 的排列 { b } \{b\} {b} { a } \{a\} {a} 的 “噬人”,当且仅当 { b } \{b\} {b} 可以被划分为两个子序列 s , t s,t s,t 满足 s ∪ t = b ∧ s ∩ t = ∅ s\cup t=b\land s\cap t=\varnothing st=bst=,且 s s s { a } \{a\} {a} 的某个前缀而 t t t { a } \{a\} {a} 的某个后缀的倒序。

求有多少个不同的 “淡淡谷的” 的 “噬人” 满足 1 1 1 是序列中第 k k k 个数。答案对大质数取模。

数据范围与提示
1 ⩽ k ⩽ n ⩽ 5 × 1 0 5 1\leqslant k\leqslant n\leqslant 5\times 10^5 1kn5×105

思路

显然需要把 { b } \{b\} {b} 划分为 “淡淡谷的” 和一个下降子序列,且 “淡淡谷的” 的末尾小于下降子序列的末尾。

根据性质和作用的不同,明显有四个子序列:

  • L L L,在 “淡淡谷的” 中,在 1 1 1 左侧(含 1 1 1 本身)的下降子序列。
  • D 1 D_1 D1,在单减子序列中,在 1 1 1 左侧的部分。
  • R R R,在 “淡淡谷的” 中,在 1 1 1 右侧的上升子序列。
  • D 2 D_2 D2,在单减子序列中,在 1 1 1 右侧的部分。

影响独立性的限制: D 1 D_1 D1 能够拼接上 D 2 D_2 D2 R R R 的值全部低于 D 2 D_2 D2,以及 ∣ R ∣ + ∣ D 2 ∣ = n − k |R|+|D_2|=n-k R+D2=nk

于是我选择了枚举 ∣ R ∣ |R| R,这样立刻得到 ∣ D 2 ∣ |D_2| D2,然后考虑 按照值的顺序 d p \tt dp dp,因此还需枚举 L L L 不超过 max ⁡ x ∈ D 2 x \max_{x\in D_2}x maxxD2x 的部分。这样就会很麻烦了。

为何按照值的顺序呢?首先,下降子序列实际是二维偏序,要么按值、要么按下标 d p \tt dp dp 。然而它似乎与连续段 d p \tt dp dp 有那么一点共性;这使我陷入错误的第一印象,终未能自拔……

我本应尝试 按照下标作 d p \tt dp dp 。因为 1 1 1 k k k 处这个限制,是明显与下标挂钩的;何不就按照下标 d p \tt dp dp 呢?记 f ( i , j ) f(i,j) f(i,j) 为,考虑了前 i i i 个数,目前划分出的两个下降子序列的末尾的排名分别是 1 1 1 2 + j    ( j ∈ N ) 2{+}j\;(j\in\N) 2+j(jN) 。第 ( i + 1 ) (i{+}1) (i+1) 个数更小,则转移到 f ( i + 1 , j + 1 ) f(i{+1},j{+}1) f(i+1,j+1),否则转移到 f ( i + 1 , t )    ( 0 ⩽ t ⩽ j ) f(i{+1},t)\;(0\leqslant t\leqslant j) f(i+1,t)(0tj)

我们求出 f ( k − 1 , j ) f(k{-}1,j) f(k1,j),然后钦定下一位是 1 1 1,得到 min ⁡ x ′ ∈ D 1 x ′ = j + 3 \min_{x'\in D_1}x'=j{+3} minxD1x=j+3 的值。注意这是相对排名。接下来把 R R R D 2 D_2 D2 放好。后面这 ( n − k ) (n{-}k) (nk) 个数,与前面的 ( 1 , j + 2 ] (1,j{+}2] (1,j+2] 之间顺序可调换,所以有系数 ( n − k + j + 1 n − k ) {n-k+j+1\choose n-k} (nknk+j+1) 。后方的内部系数,就是 2 n − k − 1 2^{n-k-1} 2nk1,即从左往右填数,要么填 max ⁡ \max max 要么填 min ⁡ \min min,但最后一位没得填。

所以问题是求出 f ( k − 1 , x ) f(k{-}1,x) f(k1,x) 的值。转移式 f ( x , y ) = f ( x − 1 , y − 1 ) + f ( x , y + 1 ) f(x,y)=f(x{-}1,y{-}1)+f(x,y{+}1) f(x,y)=f(x1,y1)+f(x,y+1),可以视作坐标系内的行走。只需要按照行走的方向,重建坐标系。在本题中,相当于 x x x 轴上的状态变为 f ( i , i ) f(i,i) f(i,i),然后其上方的状态为 f ( i , i − 1 ) f(i,i{-}1) f(i,i1) 。这样,移动就是向上和向右(即 x x x 轴正方向)了。限制条件 i ⩾ 0 i\geqslant 0 i0,恰好变为不超过该坐标系内直线 ℓ : y = x \ell:y=x :y=x

初状态有些离谱。但是,只要在序列开头加上假想的 a 0 = + ∞ a_0=+\infty a0=+,并强制要求它与 a 1 a_1 a1 不在同一个下降子序列中,就可以发现 f ( 1 , 0 ) = 1 f(1,0)=1 f(1,0)=1 了。得到一个比较经典的类卡特兰数呢!起点恰好在 ( 1 , 1 ) (1,1) (1,1),直接写出 f ( x , y ) = ( 2 x − y − 2 x − 1 ) − ( 2 x − y − 2 x ) f(x,y)={2x-y-2\choose x-1}-{2x-y-2\choose x} f(x,y)=(x12xy2)(x2xy2) 并无难度。

于是就 O ( n ) \mathcal O(n) O(n) 做完了。不幸的是,有人丧心病狂,还要再进一步。把式子写成最终形式
a n s = 2 n − k − 1 ∑ j = 0 k − 2 f ( k − 1 , j ) ( n − k + j + 1 n − k ) = 2 n − k − 1 ∑ j = 0 k − 2 [ ( 2 k − 4 − j k − 2 ) − ( 2 k − 4 − j k − 1 ) ] ( n − k + j + 1 n − k ) = 2 n − k − 1 [ ( n + k − 2 n − 1 ) − ( n + k − 2 n ) ] ans=2^{n-k-1}\sum_{j=0}^{k-2}f(k{-1},j){n-k+j+1\choose n-k}\\ =2^{n-k-1}\sum_{j=0}^{k-2}\left[{2k-4-j\choose k-2}-{2k-4-j\choose k-1}\right]{n-k+j+1\choose n-k}\\ =2^{n-k-1}\left[{n+k-2\choose n-1}-{n+k-2\choose n}\right] ans=2nk1j=0k2f(k1,j)(nknk+j+1)=2nk1j=0k2[(k22k4j)(k12k4j)](nknk+j+1)=2nk1[(n1n+k2)(nn+k2)]
所以式子更简单了。注意一个边界情况是 k = n k=n k=n,此时 1 1 1 右侧的方案数是 1 1 1,即直接去掉系数 2 n − k − 1 2^{n-k-1} 2nk1 即可。

代码

#include <cstdio> // JZM yydJUNK!!!
#include <iostream> // XJX yyds!!!
#include <algorithm> // XYX yydLONELY!!!
#include <cstring> // DDG yydOLDGOD!!!
#include <cctype> // ZXY yydBUS!!!
typedef long long llong;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)
# define drep(i,a,b) for(int i=(a); i>=(b); --i)
# define rep0(i,a,b) for(int i=(a); i!=(b); ++i)
inline int readint(){
	int a = 0, c = getchar(), f = 1;
	for(; !isdigit(c); c=getchar()) if(c == '-') f = -f;
	for(; isdigit(c); c=getchar()) a = a*10+(c^48);
	return a*f;
}

const int MAXN = 1000005;
int jc[MAXN], inv[MAXN];
unsigned int mod;
void prepare(const int &n){
	jc[0] = jc[1] = inv[0] = inv[1] = 1;
	rep(i,2,n) jc[i] = int(llong(jc[i-1])*i%mod);
	rep(i,2,n) inv[i] = int(llong(mod-mod/i)*inv[mod%i]%mod);
	rep(i,2,n) inv[i] = int(llong(inv[i])*inv[i-1]%mod);
}
inline llong getC(const int &n, const int &m){
	return llong(jc[n])*inv[m]%mod*inv[n-m]%mod;
}

unsigned powtwo[MAXN];
int main(){
	int n = readint(), k = readint();
	mod = readint();
	rep(i,powtwo[0]=1,n){
		powtwo[i] = powtwo[i-1]<<1;
		if(powtwo[i] > mod) powtwo[i] -= mod;
	}
	prepare(n<<1);
	llong ans = getC(n+k-2,n-1)-getC(n+k-2,n);
	if(ans < 0) ans += mod; // be positive
	if(n != k) ans = ans*powtwo[n-k-1]%mod;
	printf("%lld\n",ans);
	return 0;
}

后记

于我而言,写《题目背景》成了一件举足轻重的事。因为很快我将远去,这个账号将会绝笔;这些《题目背景》却忠实地记载了一段传说、一个英雄、一份孤独。

我不配成为 O U Y E \sf OUYE OUYE 的同行者;只是见证,我已经非常庆幸了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值