考 虑 最 大 值 和 最 小 值 贡 献 。 考虑最大值和最小值贡献。 考虑最大值和最小值贡献。
先 看 最 大 值 : 先看最大值: 先看最大值:
假 设 我 们 选 择 最 大 值 为 x , 则 剩 下 m − 1 个 位 置 只 能 选 不 超 过 x 的 数 字 假设我们选择最大值为x,则剩下m-1个位置只能选不超过x的数字 假设我们选择最大值为x,则剩下m−1个位置只能选不超过x的数字
题 目 表 示 排 完 序 之 后 本 质 不 同 ! \red{题目表示排完序之后本质不同!} 题目表示排完序之后本质不同!
所 以 就 是 在 不 超 过 x 的 数 字 中 任 意 重 复 选 择 m − 1 个 并 且 生 成 不 递 减 序 列 的 个 数 。 所以就是在不超过x的数字中任意重复选择m-1个并且生成不递减序列的个数。 所以就是在不超过x的数字中任意重复选择m−1个并且生成不递减序列的个数。
没 错 , n 个 中 选 m 个 数 ( 可 重 复 ) 且 不 递 减 序 列 个 数 为 C n + m − 1 m 。 请 自 行 百 度 ! 没错,n个中选m个数(可重复)且不递减序列个数为C_{n+m-1}^{m}。请自行百度! 没错,n个中选m个数(可重复)且不递减序列个数为Cn+m−1m。请自行百度!
x = n 时 , 贡 献 为 n ∗ C n + m − 2 m − 1 x=n时,贡献为n*C_{n+m-2}^{m-1} x=n时,贡献为n∗Cn+m−2m−1
x = n − 1 时 , 贡 献 为 ( n − 1 ) ∗ C n − 1 + m − 2 m − 1 x=n-1时,贡献为(n-1)*C_{n-1+m-2}^{m-1} x=n−1时,贡献为(n−1)∗Cn−1+m−2m−1
…
所 以 我 们 最 大 值 的 贡 献 就 是 所以我们最大值的贡献就是 所以我们最大值的贡献就是
∑ i = 1 n ( n − i + 1 ) ∗ C n − i + 1 + m − 2 m − 1 \sum_{i=1}^n(n-i+1)*C_{n-i+1+m-2}^{m-1} i=1∑n(n−i+1)∗Cn−i+1+m−2m−1
同 理 , 最 小 值 就 是 m − 1 个 位 置 必 须 选 择 不 小 于 x 的 数 字 , 贡 献 就 是 同理,最小值就是m-1个位置必须选择不小于x的数字,贡献就是 同理,最小值就是m−1个位置必须选择不小于x的数字,贡献就是
∑ i = 1 n i ∗ C n − i + 1 + m − 2 m − 1 \sum_{i=1}^ni*C_{n-i+1+m-2}^{m-1} i=1∑ni∗Cn−i+1+m−2m−1
这 两 个 式 子 是 我 化 简 过 后 的 。 难 点 就 是 不 递 减 序 列 个 数 是 多 少 。 \red{这两个式子是我化简过后的。难点就是不递减序列个数是多少。} 这两个式子是我化简过后的。难点就是不递减序列个数是多少。
两 个 减 一 减 得 : 两个减一减得: 两个减一减得:
∑ i = 1 n ( n − i + 1 ) ∗ C n − i + m − 1 m − 1 \sum_{i=1}^n(n-i+1)*C_{n-i+m-1}^{m-1} i=1∑n(n−i+1)∗Cn−i+m−1m−1
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
ll f[N], invF[N], inv[N];
void Init()
{
f[0] = f[1] = inv[0] = inv[1] = invF[0] = invF[1] = 1;
for(int i = 2;i < N; i++)
{
f[i] = f[i - 1] * i % mod;
inv[i] = mod - (mod / i) * inv[mod % i] % mod;
invF[i] = invF[i - 1] * inv[i] % mod;
}
}
ll C(ll m, ll n)
{
if(m < 0 || n < 0 || n > m)
return 0;
ll ans = f[m];
ans = ans * invF[n] % mod;
ans = ans * invF[m - n] % mod;
return ans;
}
//ll quick_pow(ll a, ll b) {
// ll ans = 1;
// while(b) {
// if(b & 1) ans = ans * a % mod;
// a = a * a % mod;
// b >>= 1;
// }
// return ans % mod;
//}
void solve() {
Init();
ll n, m; cin >> n >> m;
ll ans = 0;
// C(n + m - 1, m) n个数中选m个不递减个数
for(ll i = 1;i <= n; i++) {
// cout << "个数:" << C(n - i + 1 + m - 1 - 1, m - 1) << endl;
ans = (ans + (n - 2 * i + 1) * C(n - i + m - 1, m - 1) % mod) % mod;
}
cout << (ans % mod + mod) % mod << endl;
}
signed main() {
solve();
}