傅芳杰

个人博客

You Deserve The Best


组合数

组合数

ydfhZR.png

根据数据量选择合适的方式

ydTFVH.png

卡特兰数

ydf5Ix.png ydf4d1.png

组合恒等式

ydfWL9.png

AcWing 885. 求组合数 I 原题链接

给定nn组询问,每组询问给定两个整数a,ba,b,请你输出Cba mod (109+7)Cab mod (109+7)的值。

输入格式

第一行包含整数nn。

接下来nn行,每行包含一组aa和bb。

输出格式

共nn行,每行输出一个询问的解。

数据范围

1≤n≤100001≤n≤10000, 1≤b≤a≤20001≤b≤a≤2000

输入样例:

3
3 1
5 3
2 2

输出样例:

3
10
1
    private static class Combination{
        private int[][] c;
        private final int n;

        public Combination(int n) {
            this.n = n;
            init();
        }
        private void init(){
            c = new int[n + 1][n + 1];
            for (int i = 0; i <= n; i++) {
                for (int j = 0; j <= i; j++) {
                    int MOD = (int) (1e9 + 7);
                    if (j == 0) c[i][j] = 1;
                    else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
                }
            }
        }
        public int com(int a, int b) {
            return c[a][b];
        }
    }

AcWing 886. 求组合数 II 原题链接

给定nn组询问,每组询问给定两个整数a,ba,b,请你输出Cba mod (109+7)Cab mod (109+7)的值。

输入格式

第一行包含整数nn。

接下来nn行,每行包含一组aa和bb。

输出格式

共nn行,每行输出一个询问的解。

数据范围

1≤n≤100001≤n≤10000, 1≤b≤a≤1051≤b≤a≤105

输入样例:

3
3 1
5 3
2 2

输出样例:

3
10
1
    private static class Combination {
        private long[] fact;
        private long[] inFact;
        private final int n;
        private final int MOD = (int) (1e9 + 7);
        private int fastPower(long a, long b, long q) {
            long res = 1L;
            while (b > 0) {
                if ((b & 1) == 1) {
                    res = res * a % q;
                }
                b >>= 1;
                a = a * a % q;
            }
            return (int) res;
        }

        public Combination(int n) {
            this.n = n;
            init();
        }
        private void init() {
            fact = new long[n];
            inFact = new long[n];
            fact[0] = inFact[0] = 1;
            for (int i = 1; i < n; i++) {
                fact[i] = fact[i - 1] * i % MOD;
                inFact[i] = inFact[i - 1] * fastPower(i, MOD - 2, MOD) % MOD;
            }
        }
        public int com(int a, int b) {
            return (int)(fact[a] * inFact[b] % MOD * inFact[a - b] % MOD);
        }
    }

AcWing 887. 求组合数 III 原题链接

给定nn组询问,每组询问给定三个整数a,b,pa,b,p,其中pp是质数,请你输出Cba mod pCab mod p的值。

输入格式

第一行包含整数nn。

接下来nn行,每行包含一组a,b,pa,b,p。

输出格式

共nn行,每行输出一个询问的解。

数据范围

1≤n≤201≤n≤20, 1≤b≤a≤10181≤b≤a≤1018, 1≤p≤1051≤p≤105,

输入样例:

3
5 3 7
3 1 5
6 4 13

输出样例:

3
3
2
    private static class Combination {
        private int mod;

        public void setMod(int mod) {
            this.mod = mod;
        }
        public Combination() {

        }
        private int fastPower(long a, long b, long q) {
            long res = 1L;
            while (b > 0) {
                if ((b & 1) == 1) {
                    res = res * a % q;
                }
                b >>= 1;
                a = a * a % q;
            }
            return (int) res;
        }
        private long com(int a, int b) {
            long res = 1L;
            for (int i = 1, j = a; i <= b; i++, j--) {
                res = res * j % mod;
                res = res * fastPower(i, mod - 2, mod) % mod;
            }
            return (int) res;
        }
        public int lucas(long a, long b) {
            if (a < mod && b < mod) {
                return (int) com((int)a, (int)b);
            }
            return (int) (com((int)(a % mod), (int)(b % mod)) * lucas(a / mod, b / mod) % mod);
        }
    }

AcWing 888. 求组合数 IV 原题链接

输入a,ba,b,求CbaCab的值。

注意结果可能很大,需要使用高精度计算。

输入格式

共一行,包含两个整数aa和bb。

输出格式

共一行,输出CbaCab的值。

数据范围

1≤b≤a≤50001≤b≤a≤5000

输入样例:

5 3

输出样例:

10
    private static class Combination{
        private int[] primes;
        private int[] sum;
        private int count;
        private boolean[] st;

        private String com(int a, int b) {
            initPrimes(a);
            initSum(a, b);
            BigInteger res = new BigInteger("1");
            for (int i = 0; i < count; i++) {
                for (int j = 0; j < sum[i]; j++) {
                    res = res.multiply(BigInteger.valueOf(primes[i]));
                }
            }
            return res.toString();
        }
        private void initPrimes(int n){
            primes = new int[n + 1];
            st = new boolean[n + 1];
            for (int i = 2; i <= n; i++) {
                if (!st[i]) primes[count++] = i;
                for (int j = 0; primes[j] <= n / i; j++) {
                    st[primes[j] * i] = true;
                    if (i % primes[j] == 0) break;
                }
            }
        }
        private void initSum(int a, int b) {
            sum = new int[count];
            for (int i = 0; i < count; i++) {
                int p = primes[i];
                sum[i] = getNumber(a, p) - getNumber(b, p) - getNumber(a - b, p);
            }
        }
        //得到n中质因子p的个数
        private int getNumber(int n, int p) {
            int res = 0;
            while (n > 0) {
                res += n / p;
                n /= p;
            }
            return res;
        }
    }

AcWing 889. 满足条件的01序列 原题链接

给定nn个00和nn个11,它们将按照某种顺序排成长度为2n2n的序列,求它们能排列成的所有序列中,能够满足任意前缀序列中00的个数都不少于11的个数的序列有多少个。

输出的答案对109+7109+7取模。

输入格式

共一行,包含整数nn。

输出格式

共一行,包含一个整数,表示答案。

数据范围

1≤n≤1051≤n≤105

输入样例:

3

输出样例:

5
    private static class Combination {
        private long[] fact;
        private long[] inFact;
        private final int n;
        private final int MOD = (int) (1e9 + 7);
        private int fastPower(long a, long b, long q) {
            long res = 1L;
            while (b > 0) {
                if ((b & 1) == 1) {
                    res = res * a % q;
                }
                b >>= 1;
                a = a * a % q;
            }
            return (int) res;
        }

        public Combination(int n) {
            this.n = n;
            init();
        }
        private void init() {
            fact = new long[n];
            inFact = new long[n];
            fact[0] = inFact[0] = 1;
            for (int i = 1; i < n; i++) {
                fact[i] = fact[i - 1] * i % MOD;
                inFact[i] = inFact[i - 1] * fastPower(i, MOD - 2, MOD) % MOD;
            }
        }
        public int com(int a, int b) {
            return (int)(fact[a] * inFact[b] % MOD * inFact[a - b] % MOD);
        }
    }

    public static void main(String[] args) {
        int n = in.nextInt();
        Combination c = new Combination(n << 1 + 5);
        // /(n+1) = *(n+1)^{-1}
        int res = (int) ((long)c.com(n << 1, n) * c.fastPower(n + 1, c.MOD - 2, c.MOD) % c.MOD);
        out.println(res);
        out.flush();
        out.close();
    }