Chgtaxihe's blog Chgtaxihe's blog
首页
练习
算法学习
读书笔记
小玩意

Chgtaxihe

首页
练习
算法学习
读书笔记
小玩意
  • 数论

    • 一些小问题
    • 二次剩余学习笔记
    • 卡特兰数学习笔记
    • 同余最短路学习笔记
    • 康托展开学习笔记
    • 快速傅里叶变换学习笔记
    • 拉格朗日插值学习笔记
    • 拓展欧几里得学习笔记
    • 斐波那契数列学习笔记
    • 斯特林数笔记
    • 本原勾股数组学习笔记
    • 模运算学习笔记
    • 欧拉函数
    • 类欧几里得学习笔记
    • 素性检测与大数分解
    • 素数计数问题
    • 组合数问题
      • 组合数为奇数的情况
      • 卢卡斯定理(求余组合数)
        • 证明
        • 例题 洛谷P3807
    • 高斯整数学习笔记
  • 动态规划

  • 暴力

  • 图论

  • 数据结构

  • 字符串

  • 几何

  • 博弈论

  • 其他

组合数问题

# 组合数性质

# 组合数为奇数的情况

组合数C(n,k)C(n,k)C(n,k)为奇数,当且仅当kkk是nnn的子码(submask)(也就是说,n&k=kn\&k=kn&k=k)


证明如下:

C(n,k)=n!k!(n−k)!C(n,k)=\frac{n!}{k!(n-k)!}C(n,k)=k!(n−k)!n!​,因此要判断C(n,k)C(n,k)C(n,k)的奇偶性,只需要知道n!,k!,(n−k)!n!,k!,(n-k)!n!,k!,(n−k)!的素数分解中222个数

设n!,k!,(n−k)!n!,k!,(n-k)!n!,k!,(n−k)!中222的个数分别为a,b,ca,b,ca,b,c,显然有a≥b+ca\ge b+ca≥b+c,当且仅当a=b+ca=b+ca=b+c时组合数为奇数

由勒让德定理,可知

a=L2(n!)=∑k≥1⌊n2k⌋a=L_2(n!)=\sum\limits_{k\ge 1} \left\lfloor \frac{n}{2^k}\right\rfloor a=L2​(n!)=k≥1∑​⌊2kn​⌋

定义函数g(x)=xg(x)=xg(x)=x,有

g(x)=x=⌊n2⌋+⌊n2⌋+(x%2)=⌊n2⌋+g(⌊n2⌋)+(x%2)=∑i≥1⌊x2i⌋+∑i≥0(⌊x2i⌋%2)=L2(x!)+∑i≥0(⌊x2i⌋%2)\newcommand{\floordiv}[2]{\left\lfloor\frac{#1}{#2}\right\rfloor}\begin{aligned}g(x)&=x\\&=\floordiv{n}{2}+\floordiv{n}{2}+(x\% 2)\\&=\floordiv{n}{2}+g(\floordiv{n}{2})+(x\% 2)\\&=\sum\limits_{i\ge1}\floordiv{x}{2^i}+\sum\limits_{i\ge0}(\floordiv{x}{2^i}\% 2)\\&=L_2(x!)+\sum\limits_{i\ge0}(\floordiv{x}{2^i}\% 2)\end{aligned} g(x)​=x=⌊2n​⌋+⌊2n​⌋+(x%2)=⌊2n​⌋+g(⌊2n​⌋)+(x%2)=i≥1∑​⌊2ix​⌋+i≥0∑​(⌊2ix​⌋%2)=L2​(x!)+i≥0∑​(⌊2ix​⌋%2)​

令f(x)=x的二进制表示中,1的个数f(x)=\text{x的二进制表示中,1的个数}f(x)=x的二进制表示中,1的个数,显然有

f(x)=∑i≥0(⌊x2i⌋%2)\newcommand{\floordiv}[2]{\left\lfloor\frac{#1}{#2}\right\rfloor}f(x)=\sum\limits_{i\ge0}(\floordiv{x}{2^i}\% 2) f(x)=i≥0∑​(⌊2ix​⌋%2)

因此,a=L2(n!)=n−f(n)a=L_2(n!)=n-f(n)a=L2​(n!)=n−f(n),同理,b=k−f(k),c=(n−k)−f(n−k)b=k-f(k),c=(n-k)-f(n-k)b=k−f(k),c=(n−k)−f(n−k)

当a=b+ca=b+ca=b+c时,即f(n)=f(k)+f(n−k)f(n)=f(k)+f(n-k)f(n)=f(k)+f(n−k)

由数学归纳法可以证明:f(n)≤f(k)+f(n−k)f(n)\le f(k)+f(n-k)f(n)≤f(k)+f(n−k),当且仅当(k&n)=k(k\&n)=k(k&n)=k时等号成立

参考:

  • https://blog.csdn.net/netown_ethereal/article/details/35234873
  • https://blog.csdn.net/weixin_40859716/article/details/84647291

# 组合数求法

# 卢卡斯定理(求余组合数)

(sp+qtp+r)=(st)(qr)modp\begin{pmatrix}sp+q\\tp+r\end{pmatrix}=\begin{pmatrix}s\\t\end{pmatrix}\begin{pmatrix}q\\r\end{pmatrix}\mod p (sp+qtp+r​)=(st​)(qr​)modp

C(n,m)%p=C(n/p,m/p)∗C(n%p,m%p)%pC(n,m)\% p=C(n/p,m/p)*C(n\%p,m\%p)\%pC(n,m)%p=C(n/p,m/p)∗C(n%p,m%p)%p (n/p,m/pn/p,m/pn/p,m/p均为板除)

编写程序时,使用下面这条等式:

Lucas(n,m,p)=C(n%p,m%p)∗Lucas(n/p,m/p,p)modpLucas(n,m,p)=C(n\%p,m\%p)*Lucas(n/p,m/p,p)\mod p Lucas(n,m,p)=C(n%p,m%p)∗Lucas(n/p,m/p,p)modp

# 证明

对于质数ppp,对于1≤i<p1\le i\lt p1≤i<p有

C(p,i)=piC(p−1,i−1)≡p×inv(i)×C(p−1,i−1)modp≡0modp\begin{aligned}C(p,i)&=\frac{p}{i}C(p-1,i-1)\\&\equiv p\times inv(i)\times C(p-1,i-1) \mod p\\&\equiv0\mod p\end{aligned} C(p,i)​=ip​C(p−1,i−1)≡p×inv(i)×C(p−1,i−1)modp≡0modp​

再由二项式定理定理得(1+x)p=1+C(p,1)x+⋯+C(p,p−1)xp−1+xp≡1+xpmodp(1+x)^p=1+C(p,1)x+\dots+C(p,p-1)x^{p-1}+x^p\equiv1+x^p\mod p(1+x)p=1+C(p,1)x+⋯+C(p,p−1)xp−1+xp≡1+xpmodp


由二项式定理可知

(1+x)n=∑i=0nC(n,i)xi(1+x)^n=\sum\limits_{i=0}\limits^{n}C(n, i)x^i (1+x)n=i=0∑n​C(n,i)xi

对于求C(n,m)C(n,m)C(n,m),可以转化为求(1+x)n(1+x)^n(1+x)n展开式中xmx^mxm的系数。

令n=sp+q,m=tp+rn=sp+q,m=tp+rn=sp+q,m=tp+r

则

(1+x)n=(1+x)sp⋅(1+x)q≡(1+xp)s⋅(1+x)qmodp\begin{aligned}(1+x)^n&=(1+x)^{sp}\cdot(1+x)^q\\&\equiv (1+x^p)^s\cdot(1+x)^q \mod p\end{aligned} (1+x)n​=(1+x)sp⋅(1+x)q≡(1+xp)s⋅(1+x)qmodp​

因此

C(n,m)xm≡C(s,t)(xp)t⋅C(q,r)xrmodp≡C(s,t)⋅C(q,r)⋅xmmodp∴C(n,m)≡C(⌊np⌋,⌊mp⌋)⋅C(n%p,m%p)modp\begin{aligned}C(n,m)x^m & \equiv C(s,t)(x^p)^t\cdot C(q,r)x^r\mod p \\& \equiv C(s,t)\cdot C(q,r)\cdot x^m\mod p\\\therefore C(n,m) & \equiv C(\lfloor \frac{n}{p}\rfloor,\lfloor \frac{m}{p} \rfloor ) \cdot C(n\%p,m\%p) \mod p\end{aligned} C(n,m)xm∴C(n,m)​≡C(s,t)(xp)t⋅C(q,r)xrmodp≡C(s,t)⋅C(q,r)⋅xmmodp≡C(⌊pn​⌋,⌊pm​⌋)⋅C(n%p,m%p)modp​

# 例题 洛谷P3807

题意:给定a,b,pa,b,pa,b,p,求C(a+b,b)modp(p≤105)C(a+b,b)\mod p\quad (p\le10^5)C(a+b,b)modp(p≤105)

#include <bits/stdc++.h>
#define ll long long

using namespace std;

ll mod;
ll inv(ll base){
    ll ret = 1, t = mod - 2;
    for(;t; t>>=1){
        if(t & 1) ret = ret * base % mod;
        base = base * base % mod;
    }
    return ret;
}
// 暴力求组合数,有优化空间
ll Comb(ll n, ll m){
    if(n < m) return 0;
    if(n - m < m) m = n - m;
    ll denom = 1, numer = 1;
    for(int i=0; i<m; i++){
        numer = numer * (n - i) % mod;
        denom = denom * (i + 1) % mod;
    }
    return numer * inv(denom) % mod;
}

ll Lucas(ll n, ll m){
    if(m == 0) return 1;
    return Lucas(n / mod, m / mod) * Comb(n % mod, m % mod) % mod;
}

signed main(){
    int t; cin >> t;
    while(t--) {
        ll a, b;
        cin >> a >> b >> mod;
        cout << Lucas(a + b, a) << '\n';
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
上次更新: 2021/02/24, 03:37:30
素数计数问题
高斯整数学习笔记

← 素数计数问题 高斯整数学习笔记→

最近更新
01
深入理解Java虚拟机
03-04
02
DNS工作原理
02-27
03
改用VuePress啦
02-23
更多文章>
Theme by Vdoing | Copyright © 2019-2021
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式