HDU 5446 Unknown Treasure

제목: C (n, m)% p 구하 기    p = p1 * p2 *....*pk;
Lucas 정리 + 중국 잉여 정리
http://blog.sina.com.cn/s/blog_12fea76590102w6ts.html
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <set>
#include <queue>
using namespace std;
#define ll long long
const int N = 20;
ll A[N], B[N];
ll q_pow(ll x,ll y, ll p){
    ll ret = 1;
    while(y){
        if(y&1)ret = (ret*x)%p;
        x = (x*x)%p;
        y >>= 1;
    }
    return ret;
}
ll Cm(ll n, ll m, ll p){
    if(n < m)return 0;
    if(n == m)return 1;
    if(m > n-m)m = n-m;
    ll ans = 1, cn = 1, cm = 1;
    while(m){
        cn = (cn * n)%p;
        cm = (cm * m)%p;
        n--,m--;
    }
    ans = (cn * q_pow(cm,p-2,p))%p;
    return ans;
}
ll Lucas(ll n, ll m, ll p){
    if(m == 0)return 1;
    return Cm(n%p,m%p,p) * Lucas(n/p, m/p, p)%p;
}
ll Ex_gcd(ll a, ll b,ll &x, ll &y){
    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }
    ll ret = Ex_gcd(b, a%b, y, x);
    y -= a/b*x;
    return ret;
}
ll multi(ll a,ll b,ll p){
    ll ret = 0;
    while(b){
        if(b&1)ret = (ret + a)%p;
        a = (a+a)%p;
        b>>=1;
    }
    return ret;
}
ll china(ll n, ll *m, ll *a){
    ll M = 1, d, y, x = 0;
    for(int i = 0; i < n; i++){
        M *= m[i];
    }

    for(int i = 0; i < n; i++){
        ll w = M / m[i];
        d = Ex_gcd(m[i], w, d, y);
        //multi(y,w,M) = w*w^-1   (w^-1) w/m[i]%M   
        x = (x + multi(multi(y, w, M), a[i], M))%M;
    }
    return (x+M)%M;
}
int main(){
    int T, k;
    ll n, m;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld%d",&n,&m,&k);
        for(int i = 0; i < k; i++){
            scanf("%lld",A+i);
            B[i] =  Lucas(n, m, A[i]);
        }
        printf("%lld
",china(k,A,B)); } return 0; }

좋은 웹페이지 즐겨찾기