zoukankan      html  css  js  c++  java
  • hdu 3037 Lucas定理

    题目可以转换成 x1+x2+……+xn=m 有多少组解,m在题中可以取0-m。

    x1+x2+...+xn = m的解的个数,利用插板法可以得到方案数为:
    (m+1)*(m+2)...(m+n-1) = C(m+n-1,n-1) = C(m+n-1,m)

    现在就需要求不大于m的,相当于对i = 0,1...,m对C(n+i-1,i)求和,根据公式C(n,k) = C(n-1,k)+C(n-1,k-1)得
    C(n-1,0)+C(n,1)+...+C(n+m-1,m)
    = C(n,0)+C(n,1)+C(n+1,2)+...+C(n+m-1,m)
    = C(n+m,m)

    现在就是要求C(n+m,m) % p,其中p是素数。
    然后利用Lucas定理的模板就可以轻松的求得C(n+m,m) % p的值
    下面简单介绍一下Lucas定理:
    Lucas定理是用来求 C(n,m) mod p的值,p是素数(从n取m组合,模上p)。
    描述为:
    Lucas(n,m,p)=C(n%p,m%p)* Lucas(n/p,m/p,p)
    Lucas(x,0,p)=1;

    求一个组合数最后可化简为(a/b)%p

    (a/b)%p可以转换成a*Inv(b,p) Inv(b,p)为b对p的逆元。

    逆元 :(b/a) (mod n) = (b * x) (mod n)。 x表示a的逆元。并且 a*x ≡ 1 (mod n ) 注意:只有当a与n互质的时候才存在逆元


    Sample Input
    2
    1 2 5
    2 1 5

    Sample Output
    3
    3

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 # include <algorithm>
     5 # include <string>
     6 # include <cmath>
     7 # include <queue>
     8 # define LL long long
     9 using namespace std ;
    10 
    11 LL  n, m, p;
    12 
    13 LL Ext_gcd(LL a,LL b,LL &x,LL &y){
    14    if(b==0) { x=1, y=0; return a; }
    15    LL ret= Ext_gcd(b,a%b,y,x);
    16    y-= a/b*x;
    17    return ret;
    18 }
    19 LL Inv(LL a,int m){   //求逆元
    20    LL d,x,y,t= (LL)m;
    21    d= Ext_gcd(a,t,x,y);
    22    if(d==1) return (x%t+t)%t;
    23    return -1;
    24 }
    25 
    26 LL Cm(LL n, LL m, LL p)  //求组合数
    27 {
    28     LL a=1, b=1;
    29     if(m>n) return 0;
    30     while(m)
    31     {
    32         a=(a*n)%p;
    33         b=(b*m)%p;
    34         m--;
    35         n--;
    36     }
    37     return (LL)a*Inv(b,p)%p;  //(a/b)%p 等价于 a*(b,p)的逆元
    38 }
    39 
    40 int Lucas(LL n, LL m, LL p)  //把n分段递归求解相乘
    41 {
    42     if(m==0) return 1;
    43     return (LL)Cm(n%p,m%p,p)*(LL)Lucas(n/p,m/p,p)%p;
    44 }
    45 
    46 int main()
    47 {
    48     //freopen("in.txt","r",stdin) ;
    49     int T;
    50     cin >> T;
    51     while(T--)
    52     {
    53         cin>>n>>m>>p ;
    54         cout<<Lucas(n+m,m,p)<<endl ;
    55     }
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    linux安装mysql
    yum命令
    java启动jar包中的指定类
    linux系统配置参数修改
    iconfont阿里巴巴矢量图标库批量保存
    Python 使用Pandas读取Excel的学习笔记
    在Ubuntu18.04的Docker中安装Oracle镜像及简单使用
    Eclipse 安装PyDev开发Python及初步使用
    Python打包工具
    MacOS下打包Python应用
  • 原文地址:https://www.cnblogs.com/mengchunchen/p/4824299.html
Copyright © 2011-2022 走看看