大组合取模之:1<=n<=m<=1e6,1<=p<=1e9

/******************************
 大组合取模之:1<=n<=m<=1e6,1<=p<=1e9
 使用:程序最开始调用getprime(),需要时调用C(n,m,p)
 复杂度:O( n*log(n) )
 ******************************/
typedef long long ll;
#define N 210000

int PRIME[N/2];

void getprime()
{
    bool pmark[N+1000];
    memset(pmark,0,sizeof(pmark));
    int pcnt=0;
    PRIME[pcnt++]=2;
    for(int i=3;i<N+1000;i+=2)
    {
        if(pmark[i]==0)
        {
            PRIME[pcnt++]=i;
            for(int j=i;j<N+1000;j+=i) pmark[j]=1;
        }
    }
}

/**************
 快速幂模板
 调用:Quk_Mul(a,b,mod)
 返回:a^b%mod
 复杂度:当mod>10^9,log(mod)*log(b),否则log(b)
 ***************/
long long Mod_Mul(long long a,long long b,long long mod)
{
    long long msum=0;
    while(b)
    {
        if(b&1) msum = (msum+a)%mod;
        b>>=1;
        a = (a+a)%mod;
    }
    return msum;
}

long long Quk_Mul(long long a,long long b,long long mod)
{
    bool qmflag=mod>1e9?1:0;
    long long qsum=1;
    while(b)
    {
        if(b&1) qsum = (qmflag==1) ? Mod_Mul(qsum,a,mod) : (qsum*a)%mod;
        b>>=1;
        a = (qmflag==1) ? Mod_Mul(a,a,mod) : (a*a)%mod;
    }
    return qsum;
}

// 得到n! 中有多少个d因子
int getdn(int n,int d)
{
    int sum=0;
    while(n)
    {
        sum += n/d;
        n/=d;
    }
    return sum;
}

ll C(int n,int m,ll p)
{
    if(m>n) return 0;
    ll sumc=1;
    for(int i=0;PRIME[i]<=n;i++)
    {
        int cnum = getdn(n,PRIME[i])-getdn(m,PRIME[i])-getdn(n-m,PRIME[i]);
        sumc = sumc*Quk_Mul(PRIME[i], cnum, p)%p;
    }
    return sumc;
}

/*
int main() {
    getprime();
    int T;
    cin>>T;
    while(T--)
    {
        int n,m,p;
        cin>>n>>m>>p;
        cout<<C(n,m,p)<<endl;
    }
    return 0;
}
*/
时间: 2024-10-14 08:45:58

大组合取模之:1<=n<=m<=1e6,1<=p<=1e9的相关文章

大组合数取模之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

poj2305-Basic remains(进制转换 + 大整数取模)

进制转换 + 大整数取模一,题意: 在b进制下,求p%m,再装换成b进制输出. 其中p为b进制大数1000位以内,m为b进制数9位以内二,思路: 1,以字符串的形式输入p,m; 2,转换:字符串->整数 十进制->b进制; 3,十进制下计算并将整形结果转换成字符串形式,并倒序储存; 4,输出.三,步骤: 1,输入p[],m[]; 2,字符串->整形 + 进制->b进制: i,进制转换语句:m2 = m2*b + m[j]-'0'; ii,大整数取模,大整数可以写成这样的形式: 12

Big Number(大整数取模)

Big Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4789    Accepted Submission(s): 3329 Problem Description As we know, Big Number is always troublesome. But it's really important in ou

FZU 2020-组合(Lucas定理+逆元解决大组合数求模)

题目地址:FZU 2020 题意:求C(n,m)%p的值(1 <= m <= n <= 10^9, m <= 10^4, m < p < 10^9, p是素数). 思路: 对于和并且p是素数,我们一般采用Lucas定理来解. 1).Lucas定理是用来求 C(n,m) mod p的值,p是素数.其描述为: 如果 那么得到 即 Lucas(n,m,p)=C(n%p,m%p)* Lucas(n/p,m/p,p) Lucas(n,0,p)=1; 2).对于大组合数求模C(N,

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 综合以上参考,我做的一下总结:

HDU 5698 大组合数取模(逆元)

瞬间移动 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1215    Accepted Submission(s): 600 Problem Description 有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝色格子),求到第n行第m列的格子有几

大组合数取模

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1119 考虑从(1,1)->(n,m)必定会向下走n-1步,向右走m-1步,那么总的走法是C(n-1+m-1,m-1). 关于组合数取模:大神博客:http://blog.csdn.net/acdreamers/article/details/8037918 1 #include <iostream> 2 #include <string.h> 3 #

【数论】2016中国大学生程序设计竞赛 - 网络选拔赛 A. A water problem (大整数取模)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5832 题意:两个星球,一个星球一年只有137天,一个星球一年只有73天 输入N(爆炸后第N天),判断这是否为这两个星球的第一天 只要这个数是137与73的公倍数就好了(0比较特殊) 坑点:N的长度不超过10000000 只能用字符串来存储 大整数整除:紫书P314 大整数整除:首先把大整数写成"自左向右"的形式:1234 = (((1*10)+2)*10+3)*10+4 然后每步取模 代码 1

大整数取模运算出现运算结果负数的解决方案

首先我们看个例子 <?php echo 12121212121 % 1000000; //结果为 -689767 //实际应该为12121 ?> 这里的取模运算(取余数)出现了BUG.那么需要声明一下,负数也是可以取模操作的,并不是出现负数就是不对的我们应该把这种长整数类型看成float型数据进行处理介绍一个函数float fmod ( float $x , float $y )返回除法的浮点数余数通过这个函数的运算,就可以得到原本想要的余数结果 <?php $a = floatval(