Combinatorics-find the number of combinations

For the number of combinations, according to the givendata rangeTo choose the right algorithm

Find the number of combinations I

The data range given in this question is suitable for direct violent solution
by using the table method. First use the complexity of 4e6 to preprocess all the cases, and then use the complexity of 1e4 to complete the query.

#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
const int MOD = 1e9 + 7;
int c[N][N];
void init()
{
    
    
    for (int i = 0; i < N; i++)
    {
    
    
        for (int j = 0; j <= i; j++)
        {
    
    
            if (!j)
                c[i][j] = 1;
            else
                c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
        }
    }
}
int main()
{
    
    
    init();
    int n;
    cin >> n;
    while (n--)
    {
    
    
        int a, b;
        cin >> a >> b;
        cout << c[a][b] << endl;
    }
    return 0;
}

Find the number of combinations II

For the data range of this question, it is not appropriate to directly give a large table of two-dimensional arrays.
We need to preprocess all the factorials and the inverse elements of factorials here.
Use the combination number formula to solve the
inverse elements here because we need to Division is transformed into multiplication (for details, please see what I wrote before)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10, MOD = 1e9 + 7;
int fact[N];   //预处理出所有的阶乘
int infact[N]; //预处理出所有阶乘的逆元
int quickmod(int a, int k, int p)
{
    
    
    int res = 1;
    while (k)
    {
    
    
        if (k & 1)
            res = (ll)res * a % p;
        a = (ll)a * a % p;
        k = k >> 1;
    }
    return res;
}
void init()
{
    
    
    fact[0] = infact[0] = 1;
    for (int i = 1; i < N; i++)
    {
    
    
        fact[i] = (ll)fact[i - 1] * i % MOD;
        infact[i] = (ll)infact[i - 1] * quickmod(i, MOD - 2, MOD) % MOD;
    }
}
int main()
{
    
    
    init();
    int n;
    cin >> n;
    while (n--)
    {
    
    
        int a, b;
        cin >> a >> b;
        cout << (ll)fact[a] * infact[b] % MOD * infact[a-b] % MOD<<endl;
    }
    return 0;
}

Find the number of combinations III

The data range given here is larger, introduce a theorem to solve
Lucas theorem:
Insert picture description here
Here you only need to apply this theorem.
In mathematical knowledge,Divide a number, you must pay attention to the form of multiplication and inverse element, Guaranteed not to appearChoice problem

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int quickmod(int a, int k, int p)
{
    
    
    int res = 1;
    while (k)
    {
    
    
        if (k & 1) res = (ll)res * a % p;
        a = (ll)a * a % p;
        k >>= 1;
    }
    return res;
}
int c(int a, int b, int p)
{
    
    
    int res = 1;
    for (int i = 1, j = a; i <= b; i ++, j -- )
    {
    
    
        res = (ll)res * j % p;
        res = (ll)res * quickmod(i, p - 2, p) % p;
    }
    return res;
}
int lucas(ll a, ll b, int p)
{
    
    
    if (a < p && b < p)
        return c(a, b, p);
    else
        return (ll)c(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
}
int main()
{
    
    
    int n;
    cin >> n;
    while (n--)
    {
    
    
        ll a, b;
        int p;
        cin >> a >> b >> p;
        cout << lucas(a, b, p) << endl;
    }
    return 0;
}

Find the number of combinations IV

Here you can use the combination number formula to solve.
If you want to directly use high-precision, you need to write a multiplication and a division, which is more troublesome.
So you can first factorize, decompose the answer into the form of factor multiplication, and use high-precision multiplication to solve the problem.

#include <bits/stdc++.h>
using namespace std;
const int N = 5010;
int primes[N], cnt;
int sum[N];
bool st[N];
void get_primes(int n)
{
    
    
    for (int i = 2; i <= n; i++)
    {
    
    
        if (!st[i])
            primes[cnt++] = i;
        for (int j = 0; primes[j] <= n / i; j++)
        {
    
    
            st[primes[j] * i] = true;
            if (i % primes[j] == 0)
                break;
        }
    }
}
int get(int n, int p) //分解质因数,求n这个数中有多少个p
{
    
    
    int res = 0;
    while (n)
    {
    
    
        res += n / p;
        n /= p;
    }
    return res;
}
vector<int> mul(vector<int> a, int b)
{
    
    
    vector<int> c;
    int t = 0;
    for (int i = 0; i < a.size(); i++)
    {
    
    
        t += a[i] * b;
        c.push_back(t % 10);
        t /= 10;
    }
    while (t)
    {
    
    
        c.push_back(t % 10);
        t /= 10;
    }
    return c;
}
int main()
{
    
    
    int a, b;
    cin >> a >> b;
    get_primes(a);
    for (int i = 0; i < cnt; i++)
        sum[i] = get(a, primes[i]) - get(a - b, primes[i]) - get(b, primes[i]);
    vector<int> res;
    res.push_back(1);
    for (int i = 0; i < cnt; i++)
        for (int j = 0; j < sum[i]; j++)
            res = mul(res, primes[i]);
    for (int i = res.size() - 1; i >= 0; i--)
        cout << res[i];
    cout<<endl;
    return 0;
}

01 sequence that meets the conditions

Cattleya number is used in this question
Insert picture description here

Insert picture description here
The 01 sequences in the abstract the subject in a coordinate system, the right represents 0, 1 indicates an upward
so prefix means that the condition of the subject every step must go y = x at the side of this line to
which This approach is to use Cattleya numbers to solve

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
int quickmod(int a, int k, int p)
{
    
    
    int res = 1;
    while (k)
    {
    
    
        if (k & 1)
            res = (ll)res * a % p;
        a = (ll)a * a % p;
        k >>= 1;
    }
    return res;
}
int main()
{
    
    
    int n;
    cin >> n;
    int a = 2 * n, b = n;
    int res = 1;
    for (int i = a; i > a - b; i--)
        res = (ll)res * i % MOD;
    for (int i = 1; i <= b; i++)
        res = (ll)res * quickmod(i, MOD - 2, MOD) % MOD;
    res = (ll)res * quickmod(n + 1, MOD - 2, MOD) % MOD;
    cout << res << endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_46126537/article/details/112094826