Hdu 5446 Unknown Treasure (2015 ACM/ICPC Asia Regional Changchun Online Lucas定理 + 中国剩余定理)

题目链接:

  Hdu 5446 Unknown Treasure

题目描述:

  就是有n个苹果,要选出来m个,问有多少种选法?还有k个素数,p1,p2,p3,...pk,结果对lcm(p1,p2,p3.....,pk)取余。

解题思路:

  Lucas + 中国剩余定理,注意的是中国剩余定理的时候有可能会爆long long。然后用一个快速加法就好辣。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 typedef __int64 LL;
  8 const int maxn = 20;
  9 
 10 LL quick_mul (LL a, LL b, LL mod)
 11 {
 12     LL res = 1;
 13     while (b)
 14     {
 15         if (b % 2)
 16             res = (res * a) % mod;
 17         a = (a * a) % mod;
 18         b /= 2;
 19     }
 20     return res;
 21 }
 22 
 23 LL quick_add (LL a, LL b, LL mod)
 24 {
 25     LL res = 0;
 26     while (b)
 27     {
 28         if (b % 2)
 29             res =(res + a) % mod;
 30         a = (a + a) % mod;
 31         b /= 2;
 32     }
 33     return res;
 34 }
 35 
 36 LL C (LL n, LL m, LL mod)
 37 {
 38     if (n < m)
 39         return 0;
 40     LL ans = 1;
 41     for (int i=1; i<=m; i++)
 42     {
 43         LL a = (n - m + i) % mod;
 44         LL b = i % mod;
 45         ans = ans * (a * quick_mul(b, mod - 2, mod) % mod) % mod;
 46     }
 47     return ans;
 48 }
 49 
 50 LL Extended_Euclid (LL a, LL b, LL &x, LL &y)
 51 {//a, b只能是正数
 52     if (b == 0)
 53     {
 54         x = 1;
 55         y = 0;
 56         return a;
 57     }
 58 
 59     LL r = Extended_Euclid (b, a%b, x, y), t;
 60     t = x;
 61     x = y;
 62     y = t - a / b * y;
 63     return r;
 64 }
 65 
 66 LL CRT (LL a[], LL b[], LL n)
 67 {
 68     LL M = 1, ans = 0;
 69     LL Mi, x, y;
 70 
 71     for (int i=0; i<n; i++)
 72         M *= a[i];
 73 
 74     for (int i=0; i<n; i++)
 75     {
 76         Mi = M / a[i];
 77         LL d = Extended_Euclid (Mi, a[i], x, y);
 78         x = (x % a[i] + a[i]) % a[i];
 79         //注意,这里的x有可能是负数要注意取mod,变成正的
 80         
 81         //或者quick_add 的第二个参数传Mi
 82         LL res = quick_add (x, Mi, M);
 83         res = quick_add (res, b[i], M);
 84         ans = (ans + res) % M;
 85     }
 86     return (ans + M) % M;
 87 }
 88 LL Lucas (LL n, LL m, LL mod)
 89 {
 90     if (m == 0)
 91         return 1;
 92     return (C(n%mod, m%mod, mod) * Lucas(n/mod, m/mod, mod)%mod);
 93 }
 94 
 95 int main ()
 96 {
 97     LL t, n, m, k, a[maxn], b[maxn];
 98     scanf ("%I64d", &t);
 99     while (t --)
100     {
101         scanf ("%I64d %I64d %I64d", &n, &m, &k);
102         for (int i=0; i<k; i++)
103         {
104             scanf ("%I64d", &a[i]);
105             b[i] = Lucas (n, m, a[i]);
106         }
107         printf ("%I64d\n", CRT (a, b, k));
108     }
109     return 0;
110 }

 

posted @ 2015-09-17 20:30  罗茜  阅读(250)  评论(0编辑  收藏  举报