东北育才 DAY2组合数取mod (comb)

组合数取模(comb)

【问题描述】

计算C(m,n)mod 9901的值

【输入格式】

从文件comb.in中输入数据。

输入的第一行包含两个整数,m和n

【输出格式】

输出到文件comb.out中。

输出一行,一个整数

【样例输入】

2 1

【样例输出】

2

【数据规模与约定】

对于 20%的数据,n<=m<=20

对于 40%的数据,n<=m<=2000

对于 100%的数据,n<=m<=20000

这道题描述很清楚,有很多种做法,第一题还是挺水的,而且很多网站上也有

自己比较懒,因为摸的数很小,写了一个半打表半lucas。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int C[9902][9902];
int main()
{
    int i,j;
    int n,m;
    cin>>n>>m;
    for(i=0;i<=9901;i++)
    {
        C[i][i]=1;
        C[i][1]=1;
        C[i][0]=1;
    }
    for(i=2;i<=9901;i++)
    {
        for(j=1;j<=i;j++)
        {
            C[i][j]=((C[i-1][j-1])%9901+(C[i-1][j])%9901)%9901;
        }
    }
    int ans=0;
    ans=(C[n/9901][m/9901]*C[n%9901][m%9901])%9901;
    cout<<ans;
}

还有一种是直接lucas..

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
LL n,m,p;
LL quick_mod(LL a, LL b)
{
    LL ans=1;
    a%=p;
    while(b)
    {
        if(b&1)
        {
            ans=ans*a%p;
            b--;
        }
        b>>=1;
        a=a*a%p;
    }
    return ans;
}
LL C(LL n, LL m)
{
    if(m>n)
    return 0;
    LL ans=1;
    for(int i=1; i<=m; i++)
    {
        LL a=(n+i-m)%p;
        LL b=i%p;
        ans=ans*(a*quick_mod(b,p-2)%p)%p;
    }
    return ans;
}
LL Lucas(LL n, LL m)
{
    if(m == 0)
    return 1;
    return C(n%p,m%p)*Lucas(n/p,m/p)%p;
}
int main()
{
    scanf("%lld%lld", &n, &m);
    p=9901;
    printf("%lld\n", Lucas(n,m));
    return 0;
}

还有一种是直接打表..这里发一下我旁边dalao写的程序

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
LL n,m,p;
LL quick_mod(LL a, LL b)
{
    LL ans=1;
    a%=p;
    while(b)
    {
        if(b&1)
        {
            ans=ans*a%p;
            b--;
        }
        b>>=1;
        a=a*a%p;
    }
    return ans;
}
LL C(LL n, LL m)
{
    if(m > n) return 0;
    LL ans = 1;
    for(int i=1; i<=m; i++)
    {
        LL a = (n + i - m) % p;
        LL b = i % p;
        ans = ans * (a * quick_mod(b, p-2) % p) % p;
    }
    return ans;
}
LL Lucas(LL n, LL m)
{
    if(m == 0) return 1;
    return C(n % p, m % p) * Lucas(n / p, m / p) % p;
}
int main()
{
    scanf("%lld%lld", &n, &m);
    p=9901;
    printf("%lld\n", Lucas(n,m));
    return 0;
}
时间: 2024-10-12 17:44:19

东北育才 DAY2组合数取mod (comb)的相关文章

组合数取mod

条件mod是质数,inv 是逆元,fac是阶层: 用于n在10^5左右 maxn=100505: ll fact[maxn],inv[maxn]; ll Pow(ll x,ll n){ ll ans=1,base=x; while(n){ if(n&1) ans=ans*base%mod; base=base*base%mod; n>>=1; } return ans; } void init(){ fact[0]=1; for (int i = 1; i < maxn; ++i

Uva12034 (组合数取模)

题意:两匹马比赛有三种比赛结果,n匹马比赛的所有可能结果总数 解法: 设答案是f[n],则假设第一名有i个人,有C(n,i)种可能,接下来还有f(n-i)种可能性,因此答案为 ΣC(n,i)f(n-i) 另外这里给出两个求组合数的模板,卢卡斯定理的p是模数,并且要求是素数,第二个是递推式,适合于n<2000的情况 1 #include<cstdio> 2 using namespace std; 3 const int maxn = 1e3; 4 const int mod = 1005

排列组合+组合数取模 HDU 5894

1 // 排列组合+组合数取模 HDU 5894 2 // 题意:n个座位不同,m个人去坐(人是一样的),每个人之间至少相隔k个座位问方案数 3 // 思路: 4 // 定好m个人 相邻人之间k个座位 剩下就剩n-(m+1)*k个座位 5 // 剩下座位去插m个不同的盒子==就等价n个相同的球放m个不同的盒子 6 // 然后组合数出来了 7 // 乘n的话是枚举座位,除m是去掉枚举第一个座位的时候,剩下人相邻的座位相对不变的情况 8 9 #include <iostream> 10 #incl

大组合数取模之lucas定理模板,1&lt;=n&lt;=m&lt;=1e9,1&lt;p&lt;=1e6,p必须为素数

typedef long long ll; /********************************** 大组合数取模之lucas定理模板,1<=n<=m<=1e9,1<p<=1e6,p必须为素数 输入:C(n,m)%p 调用lucas(n,m,p) 复杂度:min(m,p)*log(m) ***********************************/ //ax + by = gcd(a,b) //传入固定值a,b.放回 d=gcd(a,b), x , y

组合数取模Lucas定理及快速幂取模

组合数取模就是求的值,根据,和的取值范围不同,采取的方法也不一样. 下面,我们来看常见的两种取值情况(m.n在64位整数型范围内) (1)  , 此时较简单,在O(n2)可承受的情况下组合数的计算可以直接用杨辉三角递推,边做加法边取模. (2) ,   ,并且是素数 本文针对该取值范围较大又不太大的情况(2)进行讨论. 这个问题可以使用Lucas定理,定理描述: 其中 这样将组合数的求解分解为小问题的乘积,下面考虑计算C(ni, mi) %p. 已知C(n, m) mod p = n!/(m!(

toj 4111 组合数取模 暴力分解

题目大意:组合数取模,n和m并不算大,p比较大且是合数. 思路:暴力分解+快速幂 注:暴力也是有区别的,分解质因数时可以用以下work函数,写的非常巧妙,摘录自互联网. 1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 5 typedef long long ll; 6 const ll mod = 1ll << 32; 7 const int N = 1000001; 8 const

[BZOJ 3129] [Sdoi2013] 方程 【容斥+组合数取模+中国剩余定理】

题目链接:BZOJ - 3129 题目分析 使用隔板法的思想,如果没有任何限制条件,那么方案数就是 C(m - 1, n - 1). 如果有一个限制条件是 xi >= Ai ,那么我们就可以将 m 减去 Ai - 1 ,相当于将这一部分固定分给 xi,就转化为无限制的情况了. 如果有一些限制条件是 xi <= Ai 呢?直接来求就不行了,但是注意到这样的限制不超过 8 个,我们可以使用容斥原理来求. 考虑容斥:考虑哪些限制条件被违反了,也就是说,有哪些限制为 xi <= Ai 却是 xi

BZOJ 3129 [Sdoi2013]方程 不定方程解的个数+组合数取模

题意:链接 方法:不定方程解的个数+组合数取模 解析: 先看n1与n2的部分的限制. 对于后半部分的限制来说,我们直接减去An1+i?1就可以转化一下求正整数解. 但是前半部分呢? 跟上一道猴子那个很像. 所以我们容斥搞就行了. 但是这道题好像不好写的地方不在这? 这题TMD不就是礼物吗! 大组合数取模如何取? 请参见我<BZOJ 礼物>的题解. 另外吐槽题干 明明是X1+X2+-+Xn=m 并不是小于等于 代码: #include <cstdio> #include <cs

Lucas定理--大组合数取模 学习笔记

维基百科:https://en.wikipedia.org/wiki/Lucas%27_theorem?setlang=zh 参考:http://blog.csdn.net/pi9nc/article/details/9615359 http://hi.baidu.com/lq731371663/item/d7261b0b26e974faa010340f http://hi.baidu.com/j_mat/item/8e3a891c258c4fe9dceecaba 综合以上参考,我做的一下总结: