排列组合
C(n,m)=C(n−1,m)+C(n−1,m−1)
void prec()
{
for(int i=0;i<=n;i++) {
c[i][0]=1;
for(int j=1;j<=n;j++) {
c[i][j]=(c[i-1][j]+c[i-1][j-1])
}
}
}
一些基本性质和简单说明
C(n,m)=C(n,n−m)
在n个物品中选m个等价于在n个物品中不选n-m个
C(n,m)=C(n−1,m−1)+C(n−1,m)
在n个物品中选m个可以看成两种操作,
首先先选一个物品出来
1:这个物品并不属于实际选的m个物品中,那么需要在n-1个物品中选m个
2:这个物品属于,那么需要在n-1个物品中选m-1个
答案为两种情况之和
2n=∑kC(n,k)
看成一个长度为n的01串的所有可能,k为所有0的数量,以左右两边表示意义相同,相等
C(n+m,r)=∑kC(n,k)+C(m,r−k)
把r件物品分别放在n中和m中即可
C(n,m)=n/m⋅C(n−1,m−1)
若先在n-1的01串中有m-1为1,则最后一个空位必定为1,那么最后1的位置最多有n种,但其中在n-1中的1为可能重复所以需要除以m(其实我觉得这个直接用公式记忆吧,毕竟好推导一点Orz…)
C(n,m)C(m,r)=C(n,r)C(n−r,m−r)
这个我是真不会证(不用公式),有没有神犇知道的说一下的说,感激不尽
可重复的组合
C(n+m−1,m)
等同于从n+m-1个元素中选出m个元素的值
一些定理和算法
卢卡斯定理:
C(n,m)≡C(n%p,m%p)C(n/p,m/p)modp
目的:为了解决当n或者m远远大于p时不能进行运算的问题,对于C的式子,只要n或者m大于P便一直递归下去
ll lucas(ll n,ll m)
{
if(!m) return 1;
return c[n%p][m%p]*lucas(n/p,m/p)%p;
}
二项式定理
(a+b)n=∑k=0C(n,k)an−kbk
欧几里德和拓展欧几里德
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
void exgcd(int a,int b,int &d,int &x,int &y)
{
if(!b) {d=a;x=1;y=0;}
else exgcd(b,a,d,y,x),y-=x*(a/b);
}
威尔逊定理
若p为质数则:
p|(p−1)!+1
中国剩余定理
LL china(int n,int a[N],int m[N])
{
LL M=1,d,y,x=0;
for(int i=1;i<=n;i++)M*=m[i];
for(int i=1;i<=n;i++) {
ll w=M/m[i];
exgcd(m[i],w,d,d,y);
x=(x+y*w*a[i])%M;
}
return (x+M)%M;
}
丢代码跑,真心不想写解析了太懒了