您的位置:首页 > 其它

hdu 5446 Unknown Treasure(lucas+中国剩余定理)

2016-05-03 22:21 351 查看


Unknown Treasure

Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 1992 Accepted Submission(s): 732



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

solution:
Lucas定理求C(n,m)%M,而中国剩余定理刚好解决后面部分。利用Lucas定理求出所有对pi取模的值,然后在用中国剩余定理求解。

这是会数论的队友zys写的,膜~
#include<stdio.h>
#define ll long long
#define ull unsigned long long
ll p[20],a[20];
ll n, m, k;
ll inv(ll a,ll MOD)
{
return a == 1 ? 1 : (MOD - MOD / a) * inv(MOD % a,MOD) % MOD;
}
ll C(ll n, ll m,ll MOD)
{
if (m < 0) return 0;
if (n < m) return 0;
if (m > n - m) m = n - m;
ll up = 1, down = 1;
for (ll i = 0; i < m; i++)
{
up = up * (n - i) % MOD;
down = down * (i + 1) % MOD;
}
return up * inv(down,MOD) % MOD;
}
ll Lucas(ll n, ll m, ll p)
{
ll ret = 1;
while (n && m) {
ll a = n % p, b = m % p;
if (a < b) return 0;
ret = ret * C(a, b, p) % p;
n /= p;
m /= p;
}
return ret;
}
ll extend_gcd(ll a, ll b, ll& x, ll& y)
{
ll d = a;
if (b != 0) {
d = extend_gcd(b, a%b, y, x);
y -= (a / b)*x;
}
else {
x = 1; y = 0;
}
return d;
}
ll qmul(ll a, ll b, ll MOD)
{
ull ans=0;
ull tem = a;
while (b)
{
if (b & 1)ans = (ans + tem) % MOD;
b >>= 1;
tem = (tem * 2) % MOD;
}
return (ll)ans;
}
ll CRT()
{
ll M = 1, Mi;
ll x, y, d, ans = 0;
for (int i = 0; i < k; i++) M *= p[i];
for (int i = 0; i < k; i++)
{
Mi = M / p[i];
d = extend_gcd(Mi, p[i], x, y);
ans = (ans + qmul(qmul(Mi,(x+p[i])%p[i],M),a[i],M)) % M;
}
if (ans < 0) ans += M;
return ans;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%I64d%I64d%I64d", &n, &m, &k);
for (int i = 0; i < k; i++)
{
scanf("%I64d", &p[i]);
a[i] = Lucas(n, m, p[i]);
}
printf("%I64d\n", CRT());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: