Unknown Treasure ————(hdu5446) 中国剩余定理+卢卡斯定理
2017-06-08 20:44
447 查看
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 mm different
apples among nn of
them and modulo it with MM. MM is
the product of several different primes.
InputOn the first line there is an integer T(T≤20)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)n,m,k(1≤m≤n≤1018,1≤k≤10) on
a line where kk is
the number of primes. Following on the next line are kk different
primes p1,...,pkp1,...,pk.
It is guaranteed that M=p1⋅p2⋅⋅⋅pk≤1018M=p1·p2···pk≤1018 and pi≤105pi≤105 for
everyi∈{1,...,k}i∈{1,...,k}.
OutputFor each test case output the correct combination on a line.
Sample Input
Sample Output
6
题意:给n,m,k,再给出k个素数,求组合数C(n,m)对k个素数的乘积取余
由于数据很大 求组合数要用卢卡斯定理,因为k个数都是素数,所以分别求出对这k个数取余的结果,在用中国剩余定理一合并就好了,注意,中国剩余定理合并的时候有可能爆longlong
#include <iostream>
#include <cstdio>
#include <cstring>
typedef long long LL;
using namespace std;
LL exp_mod(LL a, LL b, LL p) {
LL res = 1;
while(b != 0) {
if(b&1) res = (res * a) % p;
a = (a*a) % p;
b >>= 1;
}
return res;
}
LL Comb(LL a, LL b, LL p) {
if(a < b) return 0;
if(a == b) return 1;
if(b > a - b) b = a - b;
LL ans = 1, ca = 1, cb = 1;
for(LL i = 0; i < b; ++i) {
ca = (ca * (a - i))%p;
cb = (cb * (b - i))%p;
}
ans = (ca*exp_mod(cb, p - 2, p)) % p;
return ans;
}
LL Lucas(LL n, LL m, LL p) {
LL ans = 1;
while(n&&m&&ans) {
ans = (ans*Comb(n%p, m%p, p)) % p;
n /= p;
m /= p;
}
return ans;
}
LL exgcd(LL a, LL b, LL& x, LL& y) {
if (b == 0) { x = 1; y = 0; return a; }
LL d = exgcd(b, a % b, y, x);
y -= x * (a / b);
return d;
}
LL mul(LL a, LL b, LL mod) {
a = (a % mod + mod) % mod;
b = (b % mod + mod) % mod;
LL ret = 0;
while(b){
if(b&1){
ret += a;
if(ret >= mod) ret -= mod;
}
b >>= 1;
a <<= 1;
if(a >= mod) a -= mod;
}
return ret;
}
LL CRT(int n, LL* a, LL* m) {
LL M = 1, d, y, x = 0;
for (int i = 0; i < n; i++) M *= m[i];
for (int i = 0; i < n; i++) {
LL w = M / m[i];
exgcd(m[i], w, d, y);
x = (x + mul(mul(y, w, M), a[i], M));
}
return (x + M) % M;
}
int main() {
int T,k;
LL n, m;
LL a[15],b[15];
scanf("%d",&T);
while(T--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cin>>n>>m>>k;
for(int i=0;i<k;i++)
{
cin>>a[i];
b[i]=Lucas(n,m,a[i]);
}
printf("%lld\n",CRT(k,b,a));
}
return 0;
}
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 mm different
apples among nn of
them and modulo it with MM. MM is
the product of several different primes.
InputOn the first line there is an integer T(T≤20)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)n,m,k(1≤m≤n≤1018,1≤k≤10) on
a line where kk is
the number of primes. Following on the next line are kk different
primes p1,...,pkp1,...,pk.
It is guaranteed that M=p1⋅p2⋅⋅⋅pk≤1018M=p1·p2···pk≤1018 and pi≤105pi≤105 for
everyi∈{1,...,k}i∈{1,...,k}.
OutputFor each test case output the correct combination on a line.
Sample Input
1 9 5 2 3 5
Sample Output
6
题意:给n,m,k,再给出k个素数,求组合数C(n,m)对k个素数的乘积取余
由于数据很大 求组合数要用卢卡斯定理,因为k个数都是素数,所以分别求出对这k个数取余的结果,在用中国剩余定理一合并就好了,注意,中国剩余定理合并的时候有可能爆longlong
#include <iostream>
#include <cstdio>
#include <cstring>
typedef long long LL;
using namespace std;
LL exp_mod(LL a, LL b, LL p) {
LL res = 1;
while(b != 0) {
if(b&1) res = (res * a) % p;
a = (a*a) % p;
b >>= 1;
}
return res;
}
LL Comb(LL a, LL b, LL p) {
if(a < b) return 0;
if(a == b) return 1;
if(b > a - b) b = a - b;
LL ans = 1, ca = 1, cb = 1;
for(LL i = 0; i < b; ++i) {
ca = (ca * (a - i))%p;
cb = (cb * (b - i))%p;
}
ans = (ca*exp_mod(cb, p - 2, p)) % p;
return ans;
}
LL Lucas(LL n, LL m, LL p) {
LL ans = 1;
while(n&&m&&ans) {
ans = (ans*Comb(n%p, m%p, p)) % p;
n /= p;
m /= p;
}
return ans;
}
LL exgcd(LL a, LL b, LL& x, LL& y) {
if (b == 0) { x = 1; y = 0; return a; }
LL d = exgcd(b, a % b, y, x);
y -= x * (a / b);
return d;
}
LL mul(LL a, LL b, LL mod) {
a = (a % mod + mod) % mod;
b = (b % mod + mod) % mod;
LL ret = 0;
while(b){
if(b&1){
ret += a;
if(ret >= mod) ret -= mod;
}
b >>= 1;
a <<= 1;
if(a >= mod) a -= mod;
}
return ret;
}
LL CRT(int n, LL* a, LL* m) {
LL M = 1, d, y, x = 0;
for (int i = 0; i < n; i++) M *= m[i];
for (int i = 0; i < n; i++) {
LL w = M / m[i];
exgcd(m[i], w, d, y);
x = (x + mul(mul(y, w, M), a[i], M));
}
return (x + M) % M;
}
int main() {
int T,k;
LL n, m;
LL a[15],b[15];
scanf("%d",&T);
while(T--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cin>>n>>m>>k;
for(int i=0;i<k;i++)
{
cin>>a[i];
b[i]=Lucas(n,m,a[i]);
}
printf("%lld\n",CRT(k,b,a));
}
return 0;
}
相关文章推荐
- Unknown Treasure---hdu5446(卢卡斯+中国剩余定理)
- hdu 5446 Unknown Treasure 卢卡斯+中国剩余定理
- [卢卡斯定理+中国剩余定理] hdu 5446 Unknown Treasure
- hdu5446(组合数取模 Lucas定理 中国剩余定理)
- 1951: [Sdoi2010]古代猪文 费马小定理+中国剩余定理+卢卡斯定理+快速幂
- HDU 5446 Unknown Treasure(中国剩余定理+卢卡斯定理)——2015 ACM/ICPC Asia Regional Changchun Online
- HDU5446 Unknown Treasure[中国剩余定理+Lucas]
- hdu5446 lucas+中国剩余定理
- hdu5446 Unknown Treasure(Lucas+中国剩余定理)
- 洛谷P2480 [SDOI2010]古代猪文(费马小定理,卢卡斯定理,中国剩余定理,线性筛)
- Lucas定理+中国剩余定理 hdu5446 Unknown Treasure
- HDU5446 Unknown Treasure(组合数膜合数-->Lucas+中国剩余定理)
- 中国剩余定理的简单应用之生理周期
- [机房练习赛4.6] equation 中国剩余定理
- 浅谈—中国剩余定理
- 中国剩余定理的完美演绎
- 中国剩余定理具体解释
- ZOJ 3562 Alice's Sequence I 中国剩余定理 不互质
- 中国剩余定理
- HDU --- 5446 Unknown Treasure 数论综合【Lucas定理 + 中国剩余定理 + 快速乘 + 思维】