您的位置:首页 > 其它

HDU 5446 Unknown Treasure Lucas+CRT

2016-04-08 19:57 344 查看
题意:给n,m,k和p1,p2….pk

求C(n,m)%p1* p2* …. pk

思路:比赛的时候并没有学…..

就是LUACS+CRT模板题

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
typedef long long LL;
#define maxn 10005
const int inf=(1<<28)-1;
LL quick_mod(LL a, LL b,LL p)
{
LL ans = 1;
a %= p;
while(b)
{
if(b & 1)
{
ans = ans * a % p;
b--;
}
b >>= 1;
a = a * a % p;
}
return ans;
}

LL C(LL n, LL m,LL p)
{
if(m > n) return 0;
LL ans = 1;
LL a=1,b=1;
for(int i=1; i<=m; i++)
{
a =a* (n + i - m)%p;
b =b* i%p;
}
ans=a*quick_mod(b,p-2,p)%p;
return ans;
}

LL Lucas(LL n, LL m,LL p)
{
if(m == 0) return 1;
return C(n % p, m % p,p) * Lucas(n / p, m / p,p) % p;
}
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 a[],LL m[],LL n)//中国剩余定理求解
{
LL aa = a[1];
LL mm = m[1];
for (int i=1; 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;
}
LL r[maxn],m[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
LL M,n,k;
scanf("%lld%lld%lld",&M,&n,&k);
for(int i=1;i<=k;++i)
{
scanf("%lld",&m[i]);
r[i]=Lucas(M,n,m[i]);
}
printf("%lld\n",CRT(r,m,k));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: