把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF1288C Two Arrays 分析

题目概述

题目链接:https://www.luogu.com.cn/problem/CF1288C

长度为 \(m\) 的序列 \(a,b\),值域为 \([1,n]\),求 \((a,b)\) 的数量满足:

  • \(a\) 单调不降。
  • \(b\) 单调不升。
  • 对于每个 \(i\),满足 \(a_i\leq b_i\)

\(1\leq n\leq 1000,1\leq m\leq 10\)

分析

这道题目直接前缀和优化 \(dp\) 就行了,但是还有更优的做法。

注意到:

  • \(a_1\leq a_2\leq a_3\leq \dots\leq a_m\)
  • \(b_1\geq b_2\geq b_3\geq \dots\geq b_m\)
  • 对于每个 \(i\),有 \(a_i\leq b_i\)

那么显然只需满足:\(b_1\geq a_m\)

那么我们把他们拼在一起,变成 \(b_m,b_{m-1},\dots,b_1,a_1,a_2,\dots,a_m\)

那么这个序列就变成了 \(2m\) 个元素,单调不上升的。

\(x_j\) 表示数字 \(j\) 这上面出现的次数。

那么只需要满足:

\[\sum_{i=1}^n x_i=2m(x_i\geq 0) \]

这是一个很经典的问题,直接插板就行了,答案为 \(C_{2m+n-1}^{n-1}\)

代码

时间复杂度 \(\mathcal{O}(n+m)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#define int long long
#define N 1005
#define M 15
#define K 1035
using namespace std;
const int mod = 1e9 + 7;
int n,m,jc[K],inv[K];
int C(int a,int b) {
    if (a < 0 || b < 0 || a < b) return 0;
    return jc[a] * inv[b] % mod * inv[a - b] % mod;
}
signed main(){
    cin >> n >> m;
    jc[0] = jc[1] = inv[0] = inv[1] = 1;
    for (int i = 2;i <= n + 2 * m;i ++) jc[i] = jc[i - 1] * i % mod,inv[i] = (mod - mod / i) * inv[mod % i] % mod;
    for (int i = 2;i <= n + 2 * m;i ++) inv[i] = inv[i - 1] * inv[i] % mod;
    cout << C(2 * m + n - 1,n - 1);
    return 0;
}
posted @ 2025-10-20 09:54  high_skyy  阅读(6)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end