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
 

题目大意:让求C(n,m)%(∏pi) 这个式子的值。

中国剩余定理:

解题思路:首先用lucas定理将求C(a,b)%p转化成求解∏C(bi,ai),这样,我们可以得到c[i]数组。然后用中国剩余定理来求x0的值,即为答案。在求解的过程中需要用到扩展欧几里得来求解Mi的逆元,由于Mi比较大,所以在乘积的时候会爆数据范围,所以改成快速乘取模的方式代替直接乘积。

#include<bits/stdc++.h>
using namespace std;
typedef long long INT;
const int maxp=1e5+200;
INT p[15],c[15];
INT fac[maxp],inv[maxp];
INT powmod(INT a,INT n,INT mod){//快速幂取模
INT ret=1;
while(n){
if(n&1){
ret=ret*a%mod;
}
n>>=1;
a = a*a%mod;
}
return ret;
}
INT mulmod(INT a,INT b,INT mod){//快速乘取模
a = (a%mod + mod) % mod; //用扩展欧几里得求出的值可能为负值
b = (b%mod + mod) % mod; //用扩展欧几里得求出的值可能为负值
INT ret=0;
while(b){
if(b&1){
ret = (ret+a)%mod;
}
b >>= 1;
a = (a<<1) % mod;
}
return ret;
}
void init(INT n){ //递推出来阶乘和逆元数组
fac[0]=1;
for(int i=1;i<n;i++){
fac[i]=fac[i-1]*i % n;
}
inv[n-1]=powmod(fac[n-1],n-2,n);
for(int i=n-2;i>=0;i--){
inv[i] = inv[i+1] * (i+1) % n;
//fac[n]*inv[fac[n]]≡1%p ==> fac[n-1]*(n*inv[fac[n]])≡1%p
}
}
INT cm(INT n,INT m,INT mod){ //用逆元求组合数取模
if(n<0||m<0||m>n){
return 0;
}
return fac[n]*inv[n-m]%mod*inv[m]%mod;
}
INT lucas(INT n,INT m,INT mod){//lucas递归求P进制时的c
if(m==0){
return 1;
}
return lucas(n/mod,m/mod,mod) * cm(n%mod,m%mod,mod) % mod;
}
INT exgcd(INT a,INT b,INT &x,INT &y){ //求b关于模a的逆元。放在y中
if(b==0) { x = 1; y = 0; return a; }
INT d = exgcd(b, a%b , y, x);
y -= x * (a / b);
return d;
}
void CRT(INT k){//中国剩余定理求解一元线性同余方程组
INT M=1,x,y;
INT ans=0;
for(int i=1;i<=k;i++){
M *= p[i];
}
for(int i=1;i<=k;i++){
INT Mi=M/p[i];
exgcd(p[i],Mi,x,y);
ans = (ans+mulmod(mulmod(y,Mi,M),c[i],M))%M ;
}
printf("%I64d\n",ans);
}
int main(){
INT n,m,k;
int t;
scanf("%d",&t);
while(t--){
scanf("%I64d%I64d%I64d",&n,&m,&k);
for(int i=1;i<=k;i++){
scanf("%I64d",&p[i]);
init(p[i]);
c[i] = lucas(n,m,p[i]);
}
CRT(k);
}
return 0;
}

  

HDU 5446——Unknown Treasure——————【CRT+lucas+exgcd+快速乘+递推求逆元】的更多相关文章

  1. HDU 5446 Unknown Treasure(Lucas定理+CRT)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5446 [题目大意] 给出一个合数M的每一个质因子,同时给出n,m,求C(n,m)%M. [题解] ...

  2. Hdu 5446 Unknown Treasure (2015 ACM/ICPC Asia Regional Changchun Online Lucas定理 + 中国剩余定理)

    题目链接: Hdu 5446 Unknown Treasure 题目描述: 就是有n个苹果,要选出来m个,问有多少种选法?还有k个素数,p1,p2,p3,...pk,结果对lcm(p1,p2,p3.. ...

  3. HDU 5446 Unknown Treasure Lucas+中国剩余定理+按位乘

    HDU 5446 Unknown Treasure 题意:求C(n, m) %(p[1] * p[2] ··· p[k])     0< n,m < 1018 思路:这题基本上算是模版题了 ...

  4. HDU 5446 Unknown Treasure Lucas+中国剩余定理

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5446 Unknown Treasure 问题描述 On the way to the next se ...

  5. hdu 5446 Unknown Treasure lucas和CRT

    Unknown Treasure Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...

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

    Unknown Treasure Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  7. hdu 5446 Unknown Treasure 卢卡斯+中国剩余定理

    Unknown Treasure Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  8. ACM学习历程—HDU 5446 Unknown Treasure(数论)(2015长春网赛1010题)

    Problem Description On the way to the next secret treasure hiding place, the mathematician discovere ...

  9. HDU 5446 Unknown Treasure

    Unknown Treasure Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

随机推荐

  1. MAC的开机启动

    之前了解到MAC下的开机启动和定时自动运行不再沿用cron,而是有自己的launchctl:把启动文件放在/Library/LaunchDaemon/xxx.plist,里面可以记录运行的时间间隔.工 ...

  2. Vue Study [2]: Vue Router

    Description The article for vue router. Original post link:https://www.cnblogs.com/markjiang7m2/p/10 ...

  3. SQL事务对并发处理的支持

    前言 继上次技术分享后,学到了关于mysql事务的许多新知识,感觉还是蛮有收获的.后来反过来想想,这些东西其实我们都接触过,最起码在自学考试的数据库系统原理那本书里面对事务的讲解,在里面就提到了事务的 ...

  4. City Game UVALive - 3029(悬线法求最大子矩阵)

    题意:多组数据(国外题好像都这样),每次n*m矩形,F表示空地,R表示障碍 求最大子矩阵(悬线法模板) 把每个格子向上延伸的空格看做一条悬线 以le[i][j],re[i][j],up[i][j]分别 ...

  5. C++基础学习7:new/delete操作符

    在C语言中,动态分配和释放内存的函数是malloc.calloc和free,而在C++语言中,new.new[].delete和delete[]操作符通常会被用来动态地分配内存和释放内存. 需要注意的 ...

  6. 黑马集合学习 自定义ArrayList01

    package demo; import java.util.Arrays; public class MyArrayList<T> { Object[] t; int size; pri ...

  7. 使用Mybatis-plus发生org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):

    容我慢慢说来,之前是使用springboot+mybatis.我一直采用xml配置文件写sql. 后来采用了mybatis-plus之后,在本地上面测试没有一点问题.一放到服务器就发生这种情况 在本地 ...

  8. ubuntu常用系统命令

    安装升级 查看软件xxx安装内容 dpkg -L xxx 查找软件库中的软件 apt-cache search 正则表达式 或 aptitude search 软件包 显示系统安装包的统计信息 apt ...

  9. java thread start到run:C++源码分析

    转:https://hunterzhao.io/post/2018/06/11/hotspot-explore-inside-java-thread-run/ 整体流程 java new Thread ...

  10. RequestContextHolder与RequestContextUtils

    org.springframework.web.servlet.support.RequestContextUtils 在spring-webmvc中, 主要用来获取WebApplicationCon ...