hdu5446 Unknown Treasure(Lucas+中国剩余定理)
2015-09-18 21:14
435 查看
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≤10
18
,1≤k≤10)
on a line where k
is the number of primes. Following on the next line are
k
different primes p
1
,...,p
k
.
It is guaranteed that M=p
1
⋅p
2
⋅⋅⋅p
k
≤10
18
and p
i
≤10
5
for every i∈{1,...,k}
.
Output
For each test case output the correct combination on a line.
Sample Input
Sample Output
Source
2015 ACM/ICPC Asia Regional Changchun Online
题意:M=p1*p2*...pk;求C(n,m)%M,pi小于10^5,n,m,M都是小于10^18。
分析:Lucas定理求C(n,m)%M,而中国剩余定理刚好解决后面部分。利用Lucas定理求出所有对pi取模的值,然后在用中国剩余定理求解。
Lucas定理不懂的可以戳这里;
中国剩余定理不懂的可以戳这里;
扩展欧几里德算法的话可以戳这里。
Ps. 刚开始学数论,这个题我看了三天博客,才略懂略懂,只能说数论这东西真尼玛难 - -
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≤10
18
,1≤k≤10)
on a line where k
is the number of primes. Following on the next line are
k
different primes p
1
,...,p
k
.
It is guaranteed that M=p
1
⋅p
2
⋅⋅⋅p
k
≤10
18
and p
i
≤10
5
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
Source
2015 ACM/ICPC Asia Regional Changchun Online
题意:M=p1*p2*...pk;求C(n,m)%M,pi小于10^5,n,m,M都是小于10^18。
分析:Lucas定理求C(n,m)%M,而中国剩余定理刚好解决后面部分。利用Lucas定理求出所有对pi取模的值,然后在用中国剩余定理求解。
Lucas定理不懂的可以戳这里;
中国剩余定理不懂的可以戳这里;
扩展欧几里德算法的话可以戳这里。
Ps. 刚开始学数论,这个题我看了三天博客,才略懂略懂,只能说数论这东西真尼玛难 - -
#include <iostream> #include <cstdio> #include <cstring> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <cmath> #include <algorithm> using namespace std; const double eps = 1e-6; const double pi = acos(-1.0); const int INF = 0x3f3f3f3f; const int MOD = 1000000007; #define ll long long #define CL(a) memset(a,0,sizeof(a)) const int maxn = 1e5 + 5; ll fac[maxn]={0,1},inv[maxn]={0,1}; ll pow_mod(ll a, ll n, ll mod)//快速幂取模 { ll ret = 1; while (n) { if (n&1) ret = ret*a%mod; a = a*a%mod; n >>= 1; } return ret; } ll Lucas(ll n, ll m, ll mod)//Lucas定理 { ll ret=1; ll mm=m,nn=n; while (mm && nn) { ll mod_m=mm%mod, mod_n=nn%mod; if (mod_n>=mod_m) ret = ret*fac[mod_n]%mod*inv[mod_m]%mod*inv[mod_n-mod_m]%mod; else { ret = 0; break; } mm/=mod; nn/=mod; } return ret; } 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 china(ll n, ll m[], ll a[])//中国剩余定理求解 { ll aa = a[0]; ll mm = m[0]; for (int i=0; i<n; i++) { ll sub = (a[i] - aa); ll d, x, y; exgcd(mm, m[i], d, x, y); if (sub % d) return -1; ll new_m = m[i]/d; new_m = (sub/d*x%new_m+new_m)%new_m; aa = mm*new_m+aa; mm = mm*m[i]/d; } aa = (aa+mm)%mm; return aa; } int main () { int cas; ll n, m, k, a[15], p[15]; scanf("%d", &cas); while (cas--) { scanf("%lld%lld%lld",&n,&m,&k); for (int i=0; i<k; i++) { scanf("%lld",&p[i]); //init(p[i]); for (int j=2; j<p[i]; j++) fac[j] = fac[j-1]*j%p[i]; inv[p[i]-1] = pow_mod(fac[p[i]-1], p[i]-2, p[i]); for (int j=p[i]-1; j>0; j--) inv[j-1] = inv[j]*j%p[i]; a[i] = Lucas(n, m, p[i]); } printf("%lld\n",china(k, p, a)); } return 0; }
相关文章推荐
- HDU 5418 Victor and World (状态压缩dp)
- 数据结构应用实例#栈&单链表#简易计算器
- 放下过去 展望未来
- HDU 4027 Can you answer these queries (有意思的线段树)
- 雨林木风Win10注册表如何修改?Win10注册表权限怎么修改
- List接口和ArrayList类练习
- AutoLayout(自动布局)入门
- Java中throws与throw的区别
- 谈谈final的作用
- UVa11292 Dragon of Loowater
- Android中的AnimationDrawable的使用
- 欧拉函数
- Bash shell 快捷键
- C语言之可重入函数 && 不可重入函数
- 猴子分桃子问题
- GPIO_Mode
- 时间复杂度标记与分析(算法分析与设计)
- 使用Dojo的 defer(延迟) 方法的基本知识
- 网络图可视化工具
- HDU 2795 Billboard(线段树单点更新)