zoukankan      html  css  js  c++  java
  • 卢卡斯定理(Lucas)

    当 p 为质数,(1 le m le n) 时,求组合数(C_{n}^{m} mod{p})

    Lucas定理

    对于质数 p, 有:

    [egin{aligned} C_{n}^{m} equiv C_{n / p}^{m / p} cdot C_{n mod{p}}^{m mod {p}} pmod{p} end{aligned} ]

    其中(n / p)(m / p) 为整除。

    证明:

    引理1:

    [egin{aligned} C_{p}^{i} equiv frac{p}{i} cdot C_{p - 1}^{i - 1} equiv 0 pmod{p} end{aligned} ]

    引理1证明:

    [egin{aligned} C_{p}^{i} = frac{p!}{i! cdot (p - i)!} = frac{p}{i} cdot frac{(p - 1)}{(i - 1)! cdot (p - i)!} end{aligned} ]

    得证。
    引理2:

    [egin{aligned} (1 + x)^p equiv 1 + x^p pmod{p} end{aligned} ]

    引理2证明:(二项式定理)

    [egin{aligned} (1 + x)^p = C_p^0 + C_p^1 cdot x + ... + C_p^p cdot x^p end{aligned} ]

    从第二项到倒数第二项都可以在模 p 意义下消掉,只剩下第一项和最后一项,得证。

    Lucas定理:
    (n = s cdot p + q, m = t cdot p + r), 则(s = left lfloor frac{m}{p} ight floor, t = left lfloor frac{m}{p} ight floor)

    [egin{aligned} (1 + x)^n = [(1 + x)^p]^s cdot (1 + x)^q equiv (1 + x^p) ^ s cdot (1 + x) ^ q equiv sum_{i = 0}^{s} (C_s^i cdot x^{ip}) cdot sum_{j = 0} ^ q (C_{q}^{j} cdot x^j) pmod{p} qquad (1) end{aligned} ]

    又因为:

    [egin{aligned} (1 + x) ^ n = (1 + x)^{sp + q} = sum_{k = 0} ^ {sp + q} C_{sp + q} ^ {k} cdot x^k qquad (2) end{aligned} ]

    因为 ((1) equiv (2) pmod{p}) , 对比其中的 (x^{tp + r})项:

    [egin{aligned} C_{sp + 1} ^ {tp + r} cdot x ^ {tp + r} equiv C_s^t cdot x^{tp} cdot C_q^ r cdot x^r pmod{p} end{aligned} ]

    [egin{aligned} C_{sp + 1} ^ {tp + r} equiv C_s^t cdot C_q^ r pmod{p} end{aligned} ]

    [egin{aligned} C_{n}^{m} equiv C_{n / p}^{m / p} cdot C_{n mod{p}}^{m mod {p}} pmod{p} end{aligned} ]

    得证。

    于是可以递归求解。

    cpp:

    lld powe(lld a, lld b, lld p) {
    	lld base = 1;
    	while(b) {
    		if(b & 1) base = (base * a) % p;
    		a = (a * a) % p; b >>= 1;
    	}
    	return base;
    }
    lld comb(lld n, lld m, lld p) {
    	if(n < m) return 0;
    	if(n == m) return 1;
    	if(m > n - n) m = n - m;
    	lld cn = 1, cm = 1;
    	for(lld i = 0; i < m; i++) {
    		cn = (cn * (n - i)) % p;
    		cm = (cm * (i + 1)) % p;
    	}
    	return (cn * powe(cm, p - 2, p)) % p;
    }
    lld lucas(lld n, lld m, lld p) {
    	lld ans = 1;
    	while(n && m && ans) {
    		ans = (ans * comb(n % p, m % p, p)) % p;
    		n /= p;
    		m /= p;
    	}
    	return ans % p;
    }
    int main() {
    	int T; scanf("%d", &T);
    	while(T--) {
    		lld n, m, p;
    		scanf("%lld%lld%lld", &n, &m, &p);
    		printf("%lld
    ", lucas(n, m, p));
    	}
    	return 0;
    }
    
  • 相关阅读:
    C# 文件类的操作---删除
    C#实现Zip压缩解压实例
    UVALIVE 2431 Binary Stirling Numbers
    UVA 10570 meeting with aliens
    UVA 306 Cipher
    UVA 10994 Simple Addition
    UVA 696 How Many Knights
    UVA 10205 Stack 'em Up
    UVA 11125 Arrange Some Marbles
    UVA 10912 Simple Minded Hashing
  • 原文地址:https://www.cnblogs.com/mcggvc/p/12895789.html
Copyright © 2011-2022 走看看