HDU 5446 Unknown Treasure Lucas+中国剩余定理+按位乘

HDU 5446 Unknown Treasure

题意:求C(n, m) %(p[1] * p[2] ··· p[k])     0< n,m < 1018

思路:这题基本上算是模版题了,Lucas定理求C(n,m),再用中国剩余定理合并模方程,因为LL相乘会越界,所以用到按位乘。

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <fstream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <deque>
  7 #include <vector>
  8 #include <queue>
  9 #include <string>
 10 #include <cstring>
 11 #include <map>
 12 #include <stack>
 13 #include <set>
 14 #define LL long long
 15 #define eps 1e-8
 16 #define INF 0x3f3f3f3f
 17 #define MAXN 10005
 18 #define MAXK 15
 19 using namespace std;
 20 LL p[MAXK], mod[MAXK];
 21 LL quick_mod(LL x, LL y, LL mod){
 22     if (y == 0) return 1;
 23     LL res = quick_mod(x, y >> 1, mod);
 24     res = res * res % mod;
 25     if (y & 1){
 26         res = res * x % mod;
 27     }
 28     return res;
 29 }
 30 LL comb(LL n, LL m, LL p){
 31     LL res = 1;
 32     for (int i = 1; i <= m; i++){
 33         LL x = (n + i - m) % p;
 34         LL y = i % p;
 35         res = res * (x * quick_mod(y, p - 2, p) % p) % p;
 36     }
 37     return res;
 38 }
 39 LL lucas(LL n, LL m, LL p){
 40     if (m == 0) return 1;
 41     return lucas(n / p, m / p, p) * comb(n % p, m % p, p) % p;
 42 }
 43 
 44 LL exgcd(LL  a, LL  b, LL & x, LL & y)
 45 {
 46     if (b == 0){
 47         x = 1;
 48         y = 0;
 49         return a;
 50     }
 51     else{
 52         LL temp = exgcd(b, a % b, x, y);
 53         LL t = y;
 54         y = x - y * (a / b);
 55         x = t;
 56         return temp;
 57     }
 58 }
 59 LL multi(LL a, LL b, LL m){
 60     LL res = 0;
 61     while (b){
 62         if (b & 1){
 63             res = (res + a) % m;
 64         }
 65         a = (a + a) % m;
 66         b >>= 1;
 67     }
 68     return (res + m) % m;
 69 }
 70 LL china(LL p[], LL mod[], LL m){
 71     LL M = 1;
 72     for (int i = 1; i <= m; i++){
 73         M *= p[i];
 74     }
 75     LL x, y, res = 0;
 76     LL d;
 77     for (int i = 1; i <= m; i++){
 78         LL s = M / p[i];
 79         d = exgcd(p[i], s, d, y);
 80         res = (res + multi(multi(y, s, M), mod[i], M)) % M;
 81     }
 82     return res;
 83 }
 84 int main()
 85 {
 86 #ifndef ONLINE_JUDGE
 87     freopen("in.txt", "r", stdin);
 88     //freopen("out.txt", "w", stdout);
 89 #endif // OPEN_FILE
 90     int T;
 91     scanf("%d", &T);
 92     LL n, m, k;
 93     while (T--){
 94         scanf("%I64d%I64d%I64d", &n, &m, &k);
 95         for (int i = 1; i <= k; i++){
 96             scanf("%I64d", &p[i]);
 97             mod[i] = lucas(n, m, p[i]);
 98         }
 99         LL ans = china(p, mod, k);
100         printf("%I64d\n", ans);
101     }
102 }

 

posted on 2015-09-16 20:57  张济  阅读(173)  评论(0编辑  收藏  举报

导航