hdoj 5446 Unknown Treasure 【lucas + CRT】
4471 ワード
Unknown Treasure Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1820 Accepted Submission(s): 671
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
Sample Output
标题:C(n,m)%(p[0]*p[1]*p[2]*...*p[k-1])を解く.ここでp[]は異なる質量数である.
考え方:p[0]*p[1]*...*p[k-1]が大きいので、lucasを直接使うことはできません.
質量数ごとに分けることを考える.
C(n, m) % p[0] = a[0], C(n, m) % p[1] = a[1]... C(n, m) % p[k-1] = a[k-1].
次の方程式のグループが得られます
A = a[0] (mod p[0])
A = a[1] (mod p[1])
...
A = a[k-1] (mod p[k-1]).
次はCRTで直接Aを求めればいいです.
問題は結果が正の整数であるとは言わなかったので,CRTが最後に0に解けると,そのまま戻る.ここでWAは3回やったo(′▽`)o
ACコード:
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
标题:C(n,m)%(p[0]*p[1]*p[2]*...*p[k-1])を解く.ここでp[]は異なる質量数である.
考え方:p[0]*p[1]*...*p[k-1]が大きいので、lucasを直接使うことはできません.
質量数ごとに分けることを考える.
C(n, m) % p[0] = a[0], C(n, m) % p[1] = a[1]... C(n, m) % p[k-1] = a[k-1].
次の方程式のグループが得られます
A = a[0] (mod p[0])
A = a[1] (mod p[1])
...
A = a[k-1] (mod p[k-1]).
次はCRTで直接Aを求めればいいです.
問題は結果が正の整数であるとは言わなかったので,CRTが最後に0に解けると,そのまま戻る.ここでWAは3回やったo(′▽`)o
ACコード:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define debug printf("1
");
using namespace std;
struct ONE
{
LL gcd(LL a, LL b){
return b == 0 ? a : gcd(b, a%b);
}
LL lcm(LL a, LL b){
return a / gcd(a, b) * b;
}
void exgcd(LL a, LL b, LL &d, LL &x, LL &y)
{
if(b == 0) {d = a, x = 1, y = 0;}
else
{
exgcd(b, a%b, d, y, x);
y -= x * (a / b);
}
}
LL CRT(LL l, LL r, LL *a, LL *m)
{
LL LCM = 1;
for(LL i = l; i <= r; i++)
LCM = LCM / gcd(LCM, m[i]) * m[i];
for(LL i = l+1; i <= r; i++)
{
LL d, x, y, A = m[l], B = m[i], c = a[i] - a[l];
exgcd(A, B, d, x, y);
if(c % d) return -1;
LL mod = m[i] / d;
LL k = ((x / d * c) % mod + mod) % mod;
a[l] = m[l] * k + a[l];
m[l] = m[l] / d * m[i];
}
//if(a[l] == 0)
// return LCM;
return a[l];
}
};
ONE crt;
LL fac[100000+10];
void getfac(LL p)
{
fac[0] = 1 % p;
for(LL i = 1; i <= p; i++)
fac[i] = fac[i-1] * i % p;
}
struct TWO
{
LL pow_mod(LL a, LL n, LL p)
{
LL ans = 1 % p;
while(n)
{
if(n & 1)
ans = ans * a % p;
a = a * a % p;
n >>= 1;
}
return ans;
}
LL C(LL n, LL m, LL p)
{
if(n < m)
return 0;
else
return fac[n] * pow_mod(fac[m]*fac[n-m]%p, p-2, p) % p;
}
LL Lucas(LL n, LL m, LL p)
{
if(m == 0)
return 1 % p;
else
return C(n%p, m%p, p) * Lucas(n/p, m/p, p) % p;
}
};
TWO LUCAS;
LL p[15], a[15], m[15];
int main()
{
LL t;
scanf("%d", &t);
while(t--)
{
LL N, M, k;
scanf("%lld%lld%lld", &N, &M, &k);
for(LL i = 0; i < k; i++)
{
scanf("%lld", &p[i]);
m[i] = p[i];
getfac(p[i]);
a[i] = LUCAS.Lucas(N, M, p[i]);
}
printf("%lld
", crt.CRT(0, k-1, a, p));
}
return 0;
}