CF1349F1 Slime and Sequences (Easy Version)

题目描述

定义一个正整数序列 p \texttt{p} p,称其是合法的当且仅当对于所有在 p \texttt{p} p中出现过且 > 1 > 1 >1的正整数 k k k,存在 i < j i<j i<j,满足 p i = k − 1 , p j = k p_i=k-1,p_j=k pi=k1,pj=k

定义 f ( k ) f(k) f(k) k k k在所有长度为 n n n的好序列中的出现次数之和。

∀ k ∈ [ 1 , n ] \forall k\in[1,n] k[1,n] f ( k ) f(k) f(k)

n ≤ 5000 n\leq 5000 n5000

解题思路

非常妙的映射!

可证明每个合法序列和一个排列一一对应:

  • 1.考虑怎么把排列对应成一个合法序列:

考虑把排列划分成若干极长的连续下降段,若第 i i i段里有数 x x x,就让 p x = i p_x=i px=i

这样构造的 p p p一定是合法的,否则就说明存在一个 k k k,使得所有 k k k的出现位置都在 k − 1 k-1 k1的出现位置前面,那么这两个连续段应该会变成一个,就矛盾了。

  • 2.一个合法序列对应一个排列

这是显然的,把上述过程逆过来就好了。

因此这是一个双射。

那么对于一个位置 i i i,它对 f ( k ) f(k) f(k)的贡献就是它被划分在第 k k k段的排列数。

对于位置 i i i,若 p i < p i + 1 p_i<p_{i+1} pi<pi+1,我们称之为一个上升

i i i被划分在第 k k k段的排列数等价与前 i i i个位置恰好有 k − 1 k-1 k1个上升。

设长度为 n n n且有 m m m个上升的排列个数为 d p n , m dp_{n,m} dpn,m,则
f ( k ) = ∑ i = 1 n d p i , k − 1 C n i ( n − i ) ! f(k)=\sum_{i=1}^ndp_{i,k-1}C_n^i(n-i)! f(k)=i=1ndpi,k1Cni(ni)!

d p n , m dp_{n,m} dpn,m的递推是好求的,考虑加入最小的数:

  • 加入后上升个数不变,有 m + 1 m+1 m+1种选择,因为可以填到末尾

  • 加入后上升个数加一,有 n − m n-m nm种选择,因为可以填到开头

总复杂度 O ( n 2 ) O(n^2) O(n2).


#include<bits/stdc++.h>
using namespace std;
const int N = 5050;
int dp[N][N];
int n;
const int mod = 998244353;
inline int myplus(int a,int b){return (a+b>=mod?a+b-mod:a+b);}
int ans[N],C[N][N],fac[N];
int main()
{
	cin>>n;
	dp[1][0]=1;
	for(int i=1;i<=n;i++)
	for(int j=0;j<=i-1;j++)
	{
		dp[i+1][j]=myplus(dp[i+1][j],1ll*dp[i][j]*(j+1)%mod);
		dp[i+1][j+1]=myplus(dp[i+1][j+1],1ll*dp[i][j]*(i-j)%mod);
	}
	C[0][0]=1;fac[0]=1;
	for(int i=1;i<=n;i++)
	{
		fac[i]=1ll*fac[i-1]*i%mod;
		C[i][0]=1;
		for(int j=1;j<=i;j++)
		C[i][j]=myplus(C[i-1][j-1],C[i-1][j]);
	}
	for(int k=1;k<=n;k++)
	for(int i=1;i<=n;i++)
	ans[k]=myplus(ans[k],1ll*dp[i][k-1]*C[n][i]%mod*fac[n-i]%mod);
	for(int i=1;i<=n;i++)printf("%d ",ans[i]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值