zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Docker 基础 B站 学习 最强 教程
    apache+php安装
    php拓展 swoole 安装
    go beego框架 入门使用 (一)
    php 使用 phpword 操作 word 读取 word
    linux + MongoDB 安装 + 部署 + 讲解 (满满干货看完记得收藏噢)
    Thanos设计简析
    Prometheus TSDB文件格式-index
    Linux Kernel文件系统写I/O流程代码分析(二)bdi_writeback
    Linux Kernel文件系统写I/O流程代码分析(一)
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4796483.html
Copyright © 2011-2022 走看看