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()); } }
相关文章推荐
- try、catch、finally 块的关系
- tar命令
- max-points-on-a-line
- 抽象工厂方法
- android之事件分发的细节说明
- Node.JS创建服务
- 分类 类扩展 继承 协议 委托
- fzuoj Problem 2236 第十四个目标(树状数组+dp)
- Struts属性驱动与模型驱动的区别
- 一个例子介绍Ant的用法
- FP-Tree算法的实现
- POJ 3498 —— March of the Penguins (枚举+最大流)
- Java多线程中join方法的理解
- Spark组件之GraphX学习8--随机图生成和TopK最大入度
- 不恰当的提示还不如不提示
- STM32_USART输入输出讲解
- linux下c++编程环境搭建,运行过程以及调试
- [置顶] Eclipse GEF
- Java语言JDBC数据库
- android数据存储SharedPreferences