hdu 5446 lucas+crt+按位乘

http://acm.hdu.edu.cn/showproblem.php?pid=5446

题意:题目意思很简单,要你求C(n,m)mod p的值 p=p1*p2*...pn;

题解:对于C(n,m)mod p 由于n,m的值很大 我们用lucas定理把n,m的范围缩小。由于模数是由若干个素数的乘积组成,那么对于最终要求的解x,我们可以用中国剩余定理求解。中国剩余定理如下:

设正整数两两互素,则同余方程组

有整数解。并且在模下的解是唯一的,解为

其中,而的逆元。

最后说一点,由于数据的范围还是比较大,在乘法求解的过程中,如果用普通的乘法,是会溢出的,这里还要用到按位乘法(具体看代#include <cstdio>#include <iostream>

#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
ll m[100],a[100];
ll mul(ll a,ll b,ll p)// 按位乘
{
    ll ret=0;
    while(b)
    {
        if(b&1) ret=(ret+a)%p;
        b=b>>1;
        a=(a+a)%p;
    }
    return ret;

}
ll exgcd(ll a,ll b,ll &x,ll &y)// 扩展欧几里得
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    ll temp=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return temp;
}
ll finv(ll a,ll m)// 求逆元
{
    ll x,y;
    ll g=exgcd(a,m,x,y);
    x=(x%m+m)%m;//
    return x;
}
ll c(ll n,ll m,ll p)
{
    if(m > n) return 0;
    ll a,b;
    a=b=1;
    while(m)
    {
        a=(a*n)%p;
        b=b*m%p;
        n--;
        m--;
    }
    return mul(a,finv(b,p),p);
}
ll lucas(ll n,ll m,int p)
{
    if(m==0) return 1;// c(n,0)=1;
    return mul(lucas(n/p,m/p,p),c(n%p,m%p,p),p);// lucas把组合数要求解的范围缩小到了p之内
}

ll crt(int len)
{
    ll sum=0;
    ll M=1;
    for(int i=1;i<=len;i++) M*=m[i];
    for(int i=1;i<=len;i++)
    {
        ll temp=M/m[i];
        sum=(sum+mul(mul(a[i],temp,M),finv(temp,m[i]),M))%M;// 这里有一个数据溢出的问题 对于相乘数据会溢出的问题 用转为二进制的按位乘法
    }
    return sum;
}

void init(ll p)
{
    fac[0]=1;
    fac[1]=1;
    for(ll i=2;i<=p;i++) fac[i]=fac[i]*i%p;
}
int main()
{
    cin.sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        ll n,mm,k;
        cin>>n>>mm>>k;
        init(k);
        for(int i=1;i<=k;i++)
        {
            cin>>m[i];
            a[i]=lucas(n,mm,m[i]);
        }
        cout<<crt(k)<<endl;
    }
    return 0;
}
时间: 2024-09-30 12:41:45

hdu 5446 lucas+crt+按位乘的相关文章

hdu 2721(字符串处理,位运算 暴力)

Persistent Bits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 201    Accepted Submission(s): 116 Problem Description WhatNext Software creates sequence generators that they hope will produce

hdu 3257 Hello World!(位运算 &amp; 模拟)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3257 Hello World! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 476    Accepted Submission(s): 180 Problem Description Your task is to print ...

HDU 5446 Unknown Treasure(Lucas定理+CRT)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5446 [题目大意] 给出一个合数M的每一个质因子,同时给出n,m,求C(n,m)%M. [题解] 首先我们可以用Lucas定理求出对答案对每个质因子的模,然后我们发现只要求解这个同余方程组就可以得到答案,所以我们用中国剩余定理解决剩下的问题. [代码] #include <cstdio> #include <cstring> #include <algorithm> u

hdu 5446 Unknown Treasure lucas和CRT

Unknown Treasure Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5446 Description On the way to the next secret treasure hiding place, the mathematician discovered a cave unknown to the map. The mathematician ent

Hdu 5446 Unknown Treasure(Lucas+中国剩余定理)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5446 思路:Lucas求出所有a[i]=C(n,m)%m[i],中国剩余定理求出最终结果x (LL*LL会爆掉,手写乘法). 中国剩余定理: 设m1,m2,....mn是两两互质的正整数,对任意给定的整数a1,a2,....an必存在整数,满足 x≡a1 (mod m1),x≡a2 (mod m2),x≡a3 (mod m3)...... 并且满足上列方程组的解x(mod m1m2m3.....mn

HDU 5446 Unknown Treasure(lucas + 中国剩余定理 + 模拟乘法)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5446 题目大意:求C(n, m) % M, 其中M为不同素数的乘积,即M=p1*p2*...*pk, 1≤k≤10.1≤m≤n≤10^18. 分析: 如果M是素数,则可以直接用lucas定理来做,但是M不是素数,而是素数的连乘积.令C(n, m)为 X ,则可以利用lucas定理分别计算出 X%p1,X%p2, ... , X % pk的值,然后用中国剩余定理来组合得到所求结果. 比较坑的地方是,

HDU 5446 中国剩余定理+lucas

Unknown Treasure Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2389    Accepted Submission(s): 885 Problem Description On the way to the next secret treasure hiding place, the mathematician

hdu 5446 Unknown Treasure 中国剩余定理+lucas

题目链接 求C(n, m)%p的值, n, m<=1e18, p = p1*p2*...pk. pi是质数. 先求出C(n, m)%pi的值, 然后这就是一个同余的式子. 用中国剩余定理求解. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define l

hdu 5446 Unknown Treasure (Lucas定理+中国剩余定理+快速乘)

题意:c( n, m)%M    M = P1 * P2 * ......* Pk (其中Pk是素数) 思路:Lucas定理中C(n,m)%M,M必须是素数,当M不是素数时,我们可以把它拆成素数的乘积 如果x=C(n,m)%M ,M=p1*p2*..*pk;  a[i]=Lucas(n,m)%pi: xΞa[1](mod p1) xΞa[2](mod p2) ... xΞa[k](mod pk) 用中国剩余定理就可以把x求出来 注意到这道题ll*ll 由于计算机底层设计的原因,做加法往往比乘法快