CodeForces 1288C

CodeForces 1288C

组合数简单应用

一般来说组合数简单应用难点在于怎么想到去构造组合数公式,一般在计数题中可能出现,计数题可能是组合数、计数DP。这题的难点就在于构造组合数公式

(m)(a_i), (m)(b_i)

(a_i leq b_i (1leq ileq n))

考虑这样的 (2m) 非下降序列:(a_1,a_2,...a_m,b_m,b_{m-1},...b_1) 即:(a_1leq a_2leq a_3...b_mleq b_{m-1}leq b_1) 可知这样是能够满足所有条件。。

那么就是要从 (n) 个数中选择 (2m) 个数满足非下降的条件,通过观察发现,只要你任取 (2m) 个数拍个序,必然满足非下降的条件,而且没有重复的情况。

这可以抽象成多重集组合数的组合数模型:

(ans = C_{n + r -1}^{n - 1} = C_{n + r -1} ^{r})

(r = 2m)

#include <bits/stdc++.h> 
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define rep(I, N) for (int I = 1; I <= (N); ++I)
#define repp(I, N) for (int I = 0; I < (N); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORR(I, A, B) for (int I = (A); I >= (B); I--)
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
const int N = 2e5 + 5;
const double eps = 1e-7;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ULL;
typedef long double LD;
typedef pair<int,int> PII;
typedef vector<int> VI;
ll pow(ll a, ll b, ll m)
{
    ll ans = 1;
    a %= m;
    while (b)
    {
        if (b & 1)
            ans = (ans % m) * (a % m) % m;
        b /= 2;
        a = (a % m) * (a % m) % m;
    }
    ans %= m;
    return ans;
}
ll inv(ll x, ll p) //x关于p的逆元,p为素数
{
    return pow(x, p - 2, p);
}
ll C(ll n, ll m, ll p) //组合数C(n, m) % p
{
    if (m > n)
        return 0;
    ll up = 1, down = 1; //分子分母;
    for (int i = n - m + 1; i <= n; i++)
        up = up * i % p;
    for (int i = 1; i <= m; i++)
        down = down * i % p;
    return up * inv(down, p) % p;
}
ll Lucas(ll n, ll m, ll p)
{
    if (m == 0)
        return 1;
    return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}
int main() {
    ll n, m;
    cin >> n >> m;
    cout << Lucas(n + 2 * m - 1, 2 * m, mod) << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/strategist-614/p/12608279.html