码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-08-15 13:00:25      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:

Unknown Treasure

Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2209    Accepted Submission(s): 821


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 k different 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
 

 

Recommend
hujie   |   We have carefully selected several similar problems for you:  5842 5841 5840 5839 5838 
 
分析:
根据Lucas求解中 每一个i:C(n,m)%pi,然后根据中国剩余定理把这些结果整合起来。就能得到答案。
注意中国剩余定理在计算当前余数与其他余数乘积的最小公倍数的gcd为1的值时候,由于数据量太大,要取模。
技术分享
#include<iostream>
#include<stdio.h>
using namespace std;
long long pri[15];
long long a[15];
long long ext_gcd(long long a,long long b,long long *x,long long *y)
{
    if(b==0)
    {
        *x=1,*y=0;
        return a;
    }
    long long r = ext_gcd(b,a%b,x,y);
    long long t = *x;
    *x= *y;
    *y = t - a/b * *y;
    return r;
}
long long quick_mod(long long n,long long m,long long mod)
{
    long long ans=1;
    while(m)
    {
        if(m&1)
            ans=(ans*n)%mod;
        m>>=1;
        n=(n*n)%mod;
    }
    return ans%mod;
}
long long get_c(long long n,long long m,long long mod)
{
    long long a=1,b=1;
    for(int i=1; i<=m; i++)
    {
        b=b*i%mod;
        a=a*(n-i+1)%mod;
    }
    return (a*(quick_mod(b,mod-2,mod)))%mod;
}
long long Lucas(long long n,long long m,long long mod)
{
    if(m==0) return 1;
    return (Lucas(n/mod,m/mod,mod)*get_c(n%mod,m%mod,mod))%mod;
}
long long mul(long long a,long long n,long long mod)
{
    a = (a%mod+mod)%mod;
    n = (n%mod+mod)%mod;
    long long ret =0;
    while(n)
    {
        if(n&1)
            ret=(ret+a)%mod;
        a=(a+a)%mod;
        n>>=1;
    }
    return ret%mod;
}
long long chinese_reminder(long long a[],long long pri[],int len)
{
    long long mul_pri=1;
    long long res=0;
    for(int i=0;i<len;i++)
    {
        mul_pri*=pri[i];
    }
    for(int i=0;i<len;i++)
    {
        long long m = mul_pri/pri[i];
        long long x,y;
        ext_gcd(pri[i],m,&x,&y);
        //res=(res+y*m*a[i])%mul_pri;
        res=(res+mul(mul(y,m,mul_pri),a[i],mul_pri))%mul_pri;
    }
    return ((res%mul_pri+mul_pri)%mul_pri);
}
int main()
{
    int t;
    long long n,m;
    int k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%I64d%I64d%d",&n,&m,&k);
        for(int i=0; i<k; i++)
            scanf("%I64d",pri+i);
        for(int i=0; i<k; i++)
        {
            a[i]=Lucas(n,m,pri[i]);
        }
        long long ans = chinese_reminder(a,pri,k);
        printf("%I64d\n",ans);
    }
    return 0;
}
View Code

 

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

标签:

原文地址:http://www.cnblogs.com/superxuezhazha/p/5772357.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!