• lucas 定理学习


    大致意思就是求组合数C(n , m) % p的值, p为一个偶数

    可以将组合数的n 和 m都理解为 p 进制的表示

    n  = ak*p^k + a(k-1)*p^(k-1) + ... + a1*p + a0

    m = bk*p^k + b(k-1)*p^(k-1) + ... + b1*p + b0

    然后C(n,m)%p = C(ak , bk) * C(a(k-1) , b(k-1)) * ... * C(a1 , b1) * C(a0 , b0) % p

    当然这其中出现 ai < bi的情况那直接视为乘以了 0

    其他情况都是正常的组合数计算

    因为p为素数,取模的过程求逆元就是利用欧拉定理来求解

    a^(-1) = a^(p-2) (mod p) 

    那么只要快速幂求a^(p-2) % p的值就行了 , 那么组合数C(ai , bi) 就可以算出来了

    HDU 4349 求C(n , i)中 0<=i<=n 中多少个可以使C(n , i)为奇数

     这里先将n转化为二进制表示,因为C(n,m)%p = C(ak , bk) * C(a(k-1) , b(k-1)) * ... * C(a1 , b1) * C(a0 , b0) % p

    那么只会出现ai = 0 , 1 bi = 0 , 1的情况

    那么只有ai=0 , bi = 1 才是C(ai , bi) = 0为偶数,其他时候都是奇数,那只要枚举每一位保证那一位出现的数字可能不超过n对应的二进制位即可

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int main() {
     5     int n;
     6     while(~scanf("%d" , &n)){
     7         int ret = 1;
     8         while(n){
     9             ret = ret*((n&1)+1);
    10             n>>=1;
    11         }
    12         printf("%d
    ",ret);
    13     }    
    14     return 0;
    15 }

    HDU 3037 一道比较裸的lucas定理的题目

    求C(n+m , n)%p的值

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 
     5 int q_pow(int a , int b , int p)
     6 {
     7     ll ret = 1;
     8     while(b){
     9         if(b&1) ret = ret*a%p;
    10         a = (ll)a*a%p;
    11         b>>=1;
    12     }
    13     return ret;
    14 }
    15 
    16 int C(int a , int b , int p)
    17 {
    18     if(b==0) return 1;
    19     if(a<b) return 0;
    20     if(a==b) return 1;
    21     int s=1 , t=1;
    22     for(int i=1 ; i<=b ; i++) s=(ll)s*(a-i+1)%p;
    23     for(int i=1 ; i<=b ; i++) t=(ll)t*i%p;
    24     //cout<<"C: "<<a<<" "<<b<<" "<<p<<" "<<s<<" "<<t<<endl;
    25     return (ll)s*q_pow(t , p-2 , p)%p;
    26 }
    27 
    28 int lucas(int a, int b,int p)
    29 {
    30     //cout<<"in: "<<a<<" "<<b<<" "<<p<<endl;
    31     if(b==0) return 1;
    32     if(a<b) return 0;
    33     if(a==b) return 1;
    34     //cout<<"en: "<<C(a%p , b%p , p)<<endl;
    35     return (ll)C(a%p , b%p , p)*lucas(a/p , b/p , p)%p;
    36 }
    37 
    38 int main() {
    39     //freopen("in.txt" , "r" , stdin);
    40     int n;
    41     scanf("%d" , &n);
    42     while(n--){
    43         int a , b , p;
    44         scanf("%d%d%d", &a , &b , &p);
    45         printf("%d
    " , lucas(a+b,a,p));
    46     }    
    47     return 0;
    48 }
  • 相关阅读:
    GhostBSD 3.0RC3,基于GNOME的FreeBSD
    Nagios 3.4.3 发布,企业级监控系统
    Jolokia 1.0.6 发布, JMX远程访问方法
    微软希望开发人员不要使 WebKit 成为新版 IE6
    Kwort Linux 3.5 正式版发布
    EJDB 1.0.24 发布,嵌入式 JSON 数据库引擎
    Pale Moon 15.3 Firefox“苍月”优化版发布
    Galera Load Balancer 0.8.1 发布
    SmartSVN V7.5 正式发布
    PostgresQL建立索引如何避免写数据锁定
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4796483.html
Copyright © 2020-2023  润新知