标签:专题 组合 scan int res long static 讲解 mod
文章目录
组合数模板
注意复杂度, 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=a4∗a2∗a0,时间复杂度为 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;
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) a−1=ap−2mod(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]=infact[i-1]*quick_pow(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则为奇数,否则偶数
标签:专题,组合,scan,int,res,long,static,讲解,mod 来源: https://blog.csdn.net/zcz5566719/article/details/110977149
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。