首页 > 其他 > 详细

HDU 5446 CRT+Lucas+快速乘

时间:2015-10-12 00:25:45      阅读:271      评论:0      收藏:0      [点我收藏+]

                                        Unknown Treasure

Problem Description
On the way to the next secret treasure hiding place, the mathematician discovered a cave unknown to the map. The mathematician entered the cave because it is there. Somewhere deep in the cave, she found a treasure chest with a combination lock and some numbers on it. After quite a research, the mathematician found out that the correct combination to the lock would be obtained by calculating how many ways are there to pick m different apples among n of them and modulo it with M. M is the product of several different primes.
 

 

Input
On the first line there is an integer T(T≤20) representing the number of test cases.

Each test case starts with three integers n,m,k(1≤m≤n≤1018,1≤k≤10) on a line where k is the number of primes. Following on the next line are kdifferent primes p1,...,pk. It is guaranteed that M=p1⋅p2⋅⋅⋅pk≤1018 and pi≤105 for every i∈{1,...,k}.
 

 

Output
For each test case output the correct combination on a line.
 

 

Sample Input
1 9 5 2 3 5
 

 

Sample Output
6
 

 

Source
 
 
题意:M=p1*p2*...pk;求C(n,m)%M,pi小于10^5,n,m,M都是小于10^18。 pi为质数
题解:首先M=x*pi(1<=i<=k)
    M不一定是质数 所以只能用Lucas定理求k次 C(n,m)%Pi得到 B[i];
   最后会得到一个同余方程组
   x≡B[0](mod p[0])
   x≡B[1](mod p[1])
   x≡B[2](mod p[2])
   ......
   解这个同余方程组 用中国剩余定理
  但ll*ll都会爆所以用快速乘
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
LL M[15],B[15];
int t;
LL n,m,p,num;
LL exgcd(LL a, LL b, LL &x, LL &y)
{
    if (!b)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL gcd = exgcd(b, a % b, x, y);
    LL t = x;
    x = y;
    y = t - (a / b) * x;
    return gcd;
}
LL mult(LL a,LL b,LL p)
{
    LL ans=0;
    while(b)
    {
        if(b&1)
            ans=(ans+a)%p;
        b>>=1;
        a=(a+a)%p;
    }
    return ans;
}
LL inverse(LL num, LL mod)
{
    LL x, y;
    exgcd(num, mod, x, y);
    return (x % mod + mod) % mod;
}

LL C(LL a, LL b, LL mod)
{
    if (b > a)
        return 0;
    LL t1 = 1, t2 = 1;
    for (int i = 1; i <= b; ++i)
    {
        t2 *= i;
        t2 %= mod;
        t1 *= (a - i + 1);
        t1 %= mod;
    }
    return mult(t1,inverse(t2, mod),mod);
}
LL lucas(LL n, LL m, LL p)
{
    if (m == 0)
        return 1;
    return mult(C(n % p, m % p, p),lucas(n / p, m / p, p),p);
}
LL China(LL m[],LL b[],int k)//m:模数 b:余数
{
    LL n=1,xx,yy;
    LL ans=0;
    for(int i=0;i<k;i++)
        n*=M[i];
    for(int i=0;i<k;i++)
    {
        LL t=n/M[i];
        exgcd(t,M[i],xx,yy);
        LL x1=mult(xx,t,n);
        LL x2=mult(x1,b[i],n);
        ans=(ans+x2)%n;
    }
    return (ans%n+n)%n;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&n,&m,&num);
        for(int i=0;i<num;i++)
        {
            scanf("%d",&p);
            M[i]=p;
            B[i]=lucas(n,m,p);
        }
        LL ans=China(M,B,num);
        printf("%lld\n",ans);
    }
    return 0;
}
来自Tisuama

 

HDU 5446 CRT+Lucas+快速乘

原文:http://www.cnblogs.com/zxhl/p/4870487.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!