Unknown Treasure
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 3056 Accepted Submission(s): 1128
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 pickm
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}.
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
题意:
问组合数 C(n,m) % M 等于多少
其中 n m M 都是 小于等于 10^18 次方的比较大的数字
并且题目给出 M 的唯一分解的所有质因子 p ,求解决上述问题
题解:
首先介绍中国剩余定理:
逆元详解:
本题中求逆元 inv数组 还利用了费马小定理,得到了一个递推性质,然后快速的求了出来
lucas定理:
C(n , m)= C(n%mod , m%mod)* lucas( n/mod , m/mod )
爆longlong的乘法取模处理:
LL mul(LL a,LL b,LL mod){///二进制,按位相乘
a=(a%mod+mod)%mod;
b=(b%mod+mod)%mod;
LL ans=0;
while(b){
if(b&1) ans+=a,ans=(ans>=mod?ans-mod:ans);
b>>=1; a<<=1;
a=(a>=mod?a-mod:a);
}
return ans;
}
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 100005
#define LL long long
LL fac[maxn],inv[maxn];
LL powmod(LL a,LL b,LL mod){
LL ans=1;
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
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;
}
LL lucas(LL n,LL m,LL mod){
LL ans=1;
while(n&&m){
LL a=n%mod,b=m%mod;
if(a<b) return 0;
ans=ans*fac[a]%mod*inv[b]%mod*inv[a-b]%mod;
n/=mod,m/=mod;
}
return ans;
}
void ex_gcd(LL a,LL b,LL gcd,LL& x,LL& y){
if(!b) x=1,y=0,gcd=a;
else ex_gcd(b,a%b,gcd,y,x),y-=x*(a/b);
}
LL mul(LL a,LL b,LL mod){
a=(a%mod+mod)%mod;
b=(b%mod+mod)%mod;
LL ans=0;
while(b){
if(b&1) ans+=a,ans=(ans>=mod?ans-mod:ans);
b>>=1; a<<=1;
a=(a>=mod?a-mod:a);
}
return ans;
}
LL china(LL n,LL* a,LL* m){
LL M=1,w,gcd,x,y,ans=0;
for(int i=0;i<n;i++) M*=m[i];
for(int i=0;i<n;i++){
w=M/m[i];
ex_gcd(m[i],w,gcd,x,y);
ans=(ans+mul(mul(y,w,M),a[i],M)+M)%M;
}
return ans;
}
int main()
{
LL k,n,m,a[20],p[20],T;
//freopen("in.txt","r",stdin);
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=0;i<k;i++){
scanf("%lld",&p[i]);
init(p[i]);
a[i]=lucas(n,m,p[i]);
}
printf("%lld\n",china(k,a,p));
}
return 0;
}

博客介绍了如何利用Lucas定理和中国剩余定理解决组合数C(n, m)对大质因数分解后的模运算问题,其中涉及到了大数乘法的取模处理技巧,适用于处理超过10^18的数值计算。内容包括逆元的计算和递推性质应用。"
6110090,936985,理解与实现DES和3DES加密算法,"['加密算法', '数据安全', '对称密码体制', '编程实践', 'Java']
503

被折叠的 条评论
为什么被折叠?



