【题解】牛客OI周赛1-提高组 C.序列 计数类DP+前缀和优化

链接:https://www.nowcoder.com/acm/contest/199/C
来源:牛客网
在这里插入图片描述
在这里插入图片描述


我们枚举不同数字的个数 x x x 。此时等价于这个问题,有 x 个箱子排成一排,任
意两个箱子之间距离不超过 k(超过 k 意味着可以把这个间距减小到 k,且是一个等价的序
列),第一个箱子和最后一个箱子的距离不超过 m 的方案数。设 F [ i , j ] F[i,j] F[i,j] 表示放置了 i i i 个箱子,第 1 1 1 个箱子和最后一个箱子的距离为 j j j 的方案数。
F [ i , j ] = ∑ l = 1 j − 1 F [ i − 1 , l ] F[i,j]=\sum_{l=1}^{j-1}F[i-1,l] F[i,j]=l=1j1F[i1,l]
注意要减去超过 k k k 的那些方案数。观察到这个状态转移方程可以利用前缀和优化至 O ( n 2 ) O(n^2) O(n2)
n n n 个位置放入 x x x 种不同数字一共有 S [ n , k ] S[n,k] S[n,k] 种不同的方法,其中 S S S 代表第二类斯特林数。
然后还要对 x x x 个数字进行大小定位,共有 x ! x! x! 种不同方法。
目标:
∑ i = 1 n ∑ j = 0 m S [ n , i ] ∗ i ! ∗ f [ i , j ] \sum_{i=1}^n\sum_{j=0}^mS[n,i]*i!*f[i,j] i=1nj=0mS[n,i]i!f[i,j]

#include
#include
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int N=2e3+10;
int n,m,k;
ll fac[N],sum[N],f[N][N],s[N][N],ans;
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    fac[0]=1;
    for(int i=1;i<=n;i++)
    {
    	s[i][1]=s[i][i]=1;fac[i]=(fac[i-1]*i)%mod;
    	for(int j=2;j

总结

初拿到这道题毫无头绪。这题转化为一个放箱子的模型,通过一系列分析利用DP求解,很巧妙。

你可能感兴趣的:(比赛,牛客网,DP优化,前缀和,计数类DP)