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

    卢卡斯定理Lucas

    在数论中,(Lucas)定理用于快速计算(C^m_n ~ \% ~p),即证明(C^m_n = prod_{i = 0} ^kC^{m_i}_{n_i})其中(m_i)(m)的因式分解,(n_i)(n)的因式分解,(p)为质数。

    (Edward~Lucas)在1878年提出。

    证明:

    首先我们将(C^i_p)进行一下变式即(C^i_j = frac{p!}{i!(p - i)!}),提出来一个(frac{p}{i})也就等于(frac{p}{i} imes frac{(p - 1)!}{(i - 1)!(p - i)})。因此我们推出:

    (C^i_p equiv frac{p}{i}C^{i - 1}_{P - 1} equiv 0 ~(mod~p))。其中(1 leq i leq p - 1)

    然后我们得到:

    ((X +1)^p equiv C_p^01^p + C_p^1X^2 + ... + C_P^PX^P)(实际上就是个多项式展开...)

    同时又同余(C_p^01^pX^0 + C_p^p1^0X^p equiv 1 + X^p (mod ~p))

    因此我们又推出:

    ((1 + X)^p equiv 1 + X^p (mod ~ p))

    接着我们可以利用数学归纳法求出((1 +X)^{p^i} equiv 1 + X^{p^i} (mod~ p))。接下来将(m)(p)进制数表示就是(sum_{i = 0} ^km_ip^i)

    并且我们还可以看出(sum_{n = 0}^{m} C_n^mX^n = (1 +X)^m = prod _{i = 0}^k((1 + X)^{p^i})^{m_i} = prod _{i = 0}^k(1 + X^{p^i})^{m_i} = prod _{i = 0}^k(sum_{n_i = 0}^{m_i} C_{n_i}^{m_i}X^{n_ip^i}))
    也就等于(prod _{i = 0}^k(sum_{n_i = 0}^{p - 1} C_{n_i}^{m_i}X^{n_ip^i}) = sum_{n_i = 0}^{k} (prod_{i - 0}^kC_{n_i}^{m_i})X^n ~ (mod ~ p))

    因为(n_i)(n)(p)进制表示,因此得证。

    模板:(Link

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    using namespace std ;
    typedef long long LL ;
    const int MAXN = 100010 ;
    LL N, M, P, X[MAXN] ;
    
    inline LL Read() {
    	LL X = 0, F = 1 ; char ch = getchar() ;
    	while (ch > '9' || ch < '0') F = (ch == '-' ? - 1 : 1), ch = getchar() ;
    	while (ch >= '0' && ch <= '9') X=(X<<1)+(X<<3)+(ch^48), ch = getchar() ;
    	return X * F ;
    }
    
    inline LL QuickPow(LL A, LL B) {
    	LL Ans = 1 ;	if (! B) return 1 % P ;
    	while (B) {
    		if (B & 1) Ans = Ans * A % P ;
    		A = A * A % P, B >>= 1 ;
    	}	return Ans ;
    }
    
    inline LL C(LL A, LL B) {
    	if (B > A) return 0 ;
    	return (X[A] * QuickPow(X[B], P - 2)) % P * QuickPow(X[A - B], P - 2) % P ;
    }
    
    inline LL Lucas(LL A, LL B) {
    	if (! B) return 1 ;
    	else return (C(A % P, B % P) * Lucas(A / P, B / P)) % P ;
    }
    
    int main() {
    	int T = Read() ; while (T --) {
    		N = Read(), M = Read(), P = Read() ;
    		X[0] = 1 ;
    		for (LL i = 1 ; i <= P ; i ++) 
    			X[i] = (X[i - 1] * i) % P ;
    		LL Ans = Lucas(N + M, N) ; 
    		printf("%lld
    ", Ans) ;
    	}	return 0 ;
    }
    
  • 相关阅读:
    关于屏幕点亮和熄灭你所需要知道的
    关于handler的使用和理解
    关于Android Task的学习
    Android触摸屏幕事件总结
    Android工作问题总结
    Android生命周期总结
    Android中如何在子线程更新UI
    Eclipse中启动tomcat无效,而手动启动可以访问的原因
    使用Spring进行文件加载进内存
    spring集成quartz定时器的使用
  • 原文地址:https://www.cnblogs.com/sue_shallow/p/Lucas.html
Copyright © 2011-2022 走看看