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

题目链接

求C(n, m)%p的值, n, m<=1e18, p = p1*p2*...pk. pi是质数。

先求出C(n, m)%pi的值, 然后这就是一个同余的式子。 用中国剩余定理求解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll long long
ll a[], b[];
void extend_Euclid(ll a, ll b, ll &x, ll &y)
{
if(b == )
{
x = ;
y = ;
return;
}
extend_Euclid(b, a % b, x, y);
ll tmp = x;
x = y;
y = tmp - (a / b) * y;
}
ll mul(ll a, ll n, ll mod)
{
a = (a%mod+mod)%mod;
n = (n%mod+mod)%mod;
ll ret = ;
while(n) {
if(n&)
ret = (ret+a)%mod;
a = (a+a)%mod;
n >>= ;
}
return ret;
}
ll CRT(ll a[],ll m[],int n)
{
ll M = ;
ll ans = ;
for(int i=; i<=n; i++)
M *= m[i];
for(int i=; i<=n; i++)
{
ll x, y;
ll Mi = M / m[i];
extend_Euclid(Mi, m[i], x, y);
ans = (ans + mul(mul(Mi, x, M), a[i], M))%M;
}
return (ans+M)%M;
}
ll pow(ll a, ll b, ll mod)
{
ll ret = ;
while(b) {
if(b&) ret = ret*a%mod;
a = a*a%mod;
b /= ;
}
return ret;
}
ll C(ll n, ll m, ll mod)
{
ll a = , b = ;
for(int i = ; i <= m; i++) {
b = b*i%mod;
a = a*(n-i+)%mod;
}
return a*pow(b, mod-, mod)%mod;
}
ll lucas(ll n, ll m, ll mod)
{
if(m == )
return ;
return lucas(n/mod, m/mod, mod)*C(n%mod, m%mod, mod)%mod;
}
int main()
{
ll t, n, m, k;
cin>>t;
while(t--) {
cin>>n>>m>>k;
for(int i = ; i <= k; i++) {
scanf("%lld", &a[i]);
}
for(int i = ; i <= k; i++) {
b[i] = lucas(n, m, a[i]);
}
ll ans = CRT(b, a, k);
cout<<ans<<endl;
}
return ;
}
上一篇:【SpringCloud微服务实战学习系列】服务治理Spring Cloud Eureka


下一篇:Live555中RTP包的打包与发送过程分析