【专题讲解】组合数相关的问题

组合数模板

在这里插入图片描述

注意复杂度, O ( N 2 ) O(N^2) O(N2),并且求解范围要求n,m小于2000。

import java.util.Scanner;

public class Main{
        static final int N=2005;
        static final int mod=(int)1e9+7;
        static int c[][]=new int[N][N];
        public static void main(String[] args) {
                Scanner scan=new Scanner(System.in);
                =====预处理===
                for(int i=0;i<N;i++)
                    for(int j=0;j<=i;j++)
                        if(j==0) c[i][j]=1;
                        else  c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
                =======================================
                int t=scan.nextInt();
                while(t-->0){
                        int a=scan.nextInt();
                        int b=scan.nextInt();
                        System.out.println(c[a][b]);
                }
        }
}

快速幂

快速幂:将幂指数b转换为二进制,例:6对应二进制为110,此时 a b = a 4 ∗ a 2 ∗ a 0 a^b =a^4*a^2*a^0 ab=a4a2a0,时间复杂度为 l g n lgn lgn.

static long mod = 100000007;
static long quick_pow(long a,long b){
        long res=1;
        while(b>0){
           if((b&1)==1) res=res*a%mod;
           a=a*a%mod; // a翻倍
           b>>=1; // 移位
        }
        return res%mod;
}

利用逆元的组合数模板

在这里插入图片描述

注意时间复杂度 O ( n l g n ) O(nlgn) O(nlgn), 范围n,m 可以达到 1 0 5 10^5 105

使用了费马小定理的, a − 1 = a p − 2 m o d ( p ) a^{-1} = a^{p-2}mod(p) a1=ap2mod(p).并且在求解幂次方面使用了快速幂。

import java.util.Scanner;

public class Main{
        static final int N=100005;
        static final int mod=(int)1e9+7;
        static long fact[]=new long[N];
        static long infact[]=new long[N];
        static long quick_pow(long a,long b){
                long res=1;
                while(b>0){
                        if((b&1)==1) res=res*a%mod;
                        a=a*a%mod;
                        b>>=1;
                }
                return res%mod;
        }
        public static void main(String[] args) {
                Scanner scan=new Scanner(System.in);
                fact[0]=infact[0]=1;
                for(int i=1;i<N;i++){
                        fact[i]=fact[i-1]*i%mod;
                        infact[i]=quick_pow(fact[i],mod-2)%mod;
                }
               int t=scan.nextInt();
               while(t-->0){
                           int a=scan.nextInt();
                           int b=scan.nextInt();
                           System.out.println(fact[a]*infact[a-b]%mod*infact[b]%mod);
               }
        }
}

Lucas定理的组合数模板

在这里插入图片描述

特点是n,m极大,因此无法直接计算,但是题目要求的只是对一个比较小的数取模。因此可以使用lucas定理简化。

Lucas定理:
在这里插入图片描述
时间复杂度降低为 O ( P l g P l g N ) O(PlgPlgN) O(PlgPlgN)

import java.util.Scanner;

public class Main{
        static int p;
        //快速幂
        static long quick_pow(long a,long b){
                long res=1;
                while(b>0){
                        if((b&1)==1) res=res*a%p;
                        a=a*a%p;
                        b>>=1;
                }
                return res;
        }
        //根据组合数定义求C(a,b) 利用了快速幂。
        static long C(long a,long b){
                long res=1;
                for(long i=1,j=a;i<=b;i++,j--){
                        res=res*j%p;
                        res=res*quick_pow(i,p-2)%p;
                }
                return res;
        }
        //卢卡斯定理
        static long lucas(long a,long b){
                if(a<p && b<p) return C(a,b);
                return C(a%p,b%p)*lucas(a/p,b/p)%p;
        }
        
        public static void main(String[] args) {
                Scanner scan=new Scanner(System.in);
                int t=scan.nextInt();
                while(t-->0){
                        long a=scan.nextLong();
                        long b=scan.nextLong();
                        p=scan.nextInt();
                        System.out.println(lucas(a,b));
                }
        }
}

判断组合数奇偶

也是可以很简单的判断,对于 C n m C_n^m Cnm,如果(n&m) == m则为奇数,否则偶数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值