zoukankan      html  css  js  c++  java
  • lucas定理 FOJ 2020 组合

     Problem 2020 组合

    Accept: 886    Submit: 2084
    Time Limit: 1000 mSec    Memory Limit : 32768 KB

    Problem Description

    给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数。例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大!于是xiaobo希望你输出 C(n,m) mod p的值!

    Input

    输入数据第一行是一个正整数T,表示数据组数 (T <= 100) 接下来是T组数据,每组数据有3个正整数 n, m, p (1 <= m <= n <= 10^9, m <= 10^4, m < p < 10^9, p是素数)

    Output

    对于每组数据,输出一个正整数,表示C(n,m) mod p的结果。

    Sample Input

    2 5 2 3 5 2 61

     Sample Output

    1 10 
    未预处理阶乘(在组合数函数中写了个循环):
     1 #include<iostream>
     2 using namespace std;
     3 #include<cstdio>
     4 #define ll long long
     5 int t;
     6 ll quick_mod(ll a,ll b,ll p)// a^b%p
     7 {
     8     a%=p;
     9     ll ans=1;
    10     while(b)
    11     {
    12         if(b&1)
    13         {
    14             b--;
    15             ans=(ans*a)%p;
    16         }
    17         b>>=1;
    18         a=(a*a)%p;
    19     }
    20     return ans;
    21 }
    22 ll C(ll n, ll m,ll p)
    23 {
    24     if(m>n) return 0;
    25     ll ans=1,a,b;
    26     for(int i=1;i<=m;++i)
    27     {
    28         a=(n+i-m)%p;
    29         b=i%p;
    30         ans=ans*(a*quick_mod(b,p-2,p)%p)%p;
    31     }
    32     return ans;
    33 }
    34 ll lucas(ll n,ll m,ll p)
    35 {
    36     if(m==0) return 1;
    37     return (lucas(n/p,m/p,p)*C(n%p,m%p,p))%p; 
    38 }
    39 int main()
    40 {
    41     scanf("%d",&t);
    42     while(t--)
    43     {
    44         ll n,m,p;
    45         cin>>n>>m>>p;
    46         cout<<lucas(n,m,p)<<endl;
    47     }
    48     return 0;
    49 }

    预处理阶乘(有时可以加快速度,相乘时也要防止溢出):

     1 /*事实上,这道题目预处理阶乘,反而会更慢,因为题目中n,m都是10^9,预处理已经接近超时了*/
     2 #include<iostream>
     3 using namespace std;
     4 #include<cstdio>
     5 #define S 10000000
     6 #define ll long long
     7 int t;
     8 long long f[1000000];
     9 void yuchuli(ll p)
    10 {
    11     f[0]=1;
    12     for(int i=1;i<=S;++i)
    13       f[i]=f[i-1]*i%p;
    14 }
    15 ll quick_mod(ll a,ll b,ll p)
    16 {
    17     a%=p;
    18     ll ans=1;
    19     while(b)
    20     {
    21         if(b&1)
    22         {
    23             b--;
    24             ans=(ans*a)%p;
    25         }
    26         b>>=1;
    27         a=(a*a)%p;
    28     }
    29     return ans;
    30 }
    31 ll C(ll n, ll m,ll p)
    32 {
    33     if(m>n) return 0;
    34     return (f[n]*quick(f[m]*f[n-m],p-2,p))%p;
    35 }
    36 ll lucas(ll n,ll m,ll p)
    37 {
    38     if(m==0) return 1;
    39     return (lucas(n/p,m/p,p)*C(n%p,m%p,p))%p; 
    40 }
    41 int main()
    42 {
    43     scanf("%d",&t);
    44     while(t--)
    45     {
    46         ll n,m,p;
    47         cin>>n>>m>>p;
    48         cout<<lucas(n,m,p)<<endl;
    49     }
    50     return 0;
    51 }
     
  • 相关阅读:
    第34天-文件_system (2013.09.04)
    第33天-文件I/O _2(2013.09.03)
    小项目 : 计算库函数中单词的个数第30天
    第32天-文件I/O _1(2013.09.02)
    嵌入式培训学习历程第二十九天
    大作业 :学生信息管理系统。。。
    嵌入式培训学习历程第二十六天
    读取一个文件中哪一行 的一个参数
    LINUX C 语言 快速获取调用SHELL命令后的结果
    C语言制造一个随机数
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5517575.html
Copyright © 2011-2022 走看看