BZOJ2142: 礼物

2142: 礼物

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 2169  Solved: 956
[Submit][Status][Discuss]

Description

一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。不同的人物在小E
心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多。小E从商店中购买了n件礼物,打算送给m个人
,其中送给第i个人礼物数量为wi。请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某
个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模P后的结果。

Input

输入的第一行包含一个正整数P,表示模;
第二行包含两个整整数n和m,分别表示小E从商店购买的礼物数和接受礼物的人数;
以下m行每行仅包含一个正整数wi,表示小E要送给第i个人的礼物数量。

Output

若不存在可行方案,则输出“Impossible”,否则输出一个整数,表示模P后的方案数。

Sample Input

100
4 2
1
2

Sample Output

12
【样例说明】
下面是对样例1的说明。
以“/”分割,“/”前后分别表示送给第一个人和第二个人的礼物编号。12种方案详情如下:
1/23 1/24 1/34
2/13 2/14 2/34
3/12 3/14 3/24
4/12 4/13 4/23
【数据规模和约定】
设P=p1^c1 * p2^c2 * p3^c3 * … *pt ^ ct,pi为质数。
对于100%的数据,1≤n≤109,1≤m≤5,1≤pi^ci≤10^5。

HINT

Source

 

【题解】

裸的exlucas

脑抽每次都暴力分解p。。。完全可以分解一次根号p的

公式: 

$\binom n {w_1}+\binom {n-w_1} {w_2}+\binom {n-w_1-w_2} {w_3}+\cdots$

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <vector>
  8 #include <map>
  9 #include <string> 
 10 #include <cmath> 
 11 #include <sstream>
 12 #define min(a, b) ((a) < (b) ? (a) : (b))
 13 #define max(a, b) ((a) > (b) ? (a) : (b))
 14 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
 15 template<class T>
 16 inline void swap(T &a, T &b)
 17 {
 18     T tmp = a;a = b;b = tmp;
 19 }
 20 inline void read(long long &x)
 21 {
 22     x = 0;char ch = getchar(), c = ch;
 23     while(ch < '0' || ch > '9') c = ch, ch = getchar();
 24     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
 25     if(c == '-') x = -x;
 26 }
 27 const long long INF = 0x3f3f3f3f;
 28 long long pow(long long a, long long b, long long mod)
 29 {
 30     long long r = 1, base = a % mod;
 31     for(;b;b >>= 1)
 32     {
 33         if(b & 1) r *= base, r %= mod;
 34         base *= base, base %= mod;
 35     }
 36     return r;
 37 }
 38 void exgcd(long long a, long long b, long long &x, long long &y)
 39 {
 40     if(!b) x = 1, y = 0;
 41     else exgcd(b, a % b, y, x), y -= (a / b) * x;
 42 }
 43 long long ni(long long x, long long mod)
 44 {
 45     long long a,b;exgcd(x, mod, a, b);
 46     a = (a % mod + mod) % mod;
 47     return !a ? mod : a;
 48 }
 49 long long calc(long long n, long long p, long long pt)
 50 {
 51     if(!n) return 1;long long ans = 1;
 52     for(long long i = 1;i <= pt;++ i) if(i % p) ans *= i, ans %= pt;
 53     ans = pow(ans, n/pt, pt);
 54     for(long long i = n%pt;i >= 1;-- i) if(i % p) ans *= i, ans %= pt;
 55     return ans * calc(n/p, p, pt) % pt;
 56 }
 57 long long C(long long n, long long m, long long p, long long pt)
 58 {
 59     if(n < m || n < 0 || m < 0) return 0;
 60     long long cnt = 0;
 61     for(long long i = n;i;i /= p) cnt += i/p;
 62     for(long long i = m;i;i /= p) cnt -= i/p;
 63     for(long long i = n - m;i;i /= p) cnt -= i/p;
 64     return pow(p, cnt, pt) * calc(n, p, pt) % pt * ni(calc(m, p, pt), pt) % pt * ni(calc(n - m, p, pt), pt) % pt;
 65 } 
 66 long long prime[100000], cnt[100000], fang[100000], tot;
 67 void fenjie(long long p)
 68 {
 69     long long tmp = sqrt(p),tmp2 = p;
 70     for(long long i = 2;i <= tmp;++ i)
 71         if(tmp2 % i == 0)
 72         {
 73             prime[++ tot] = i, fang[tot] = 1;
 74             while(tmp2 % i == 0) ++ cnt[tot], tmp2 /= i, fang[tot] *= i;
 75         }
 76     if(tmp2 > 1) prime[++ tot] = tmp2, cnt[tot] = 1, fang[tot] = tmp2;
 77 }
 78 long long exlucas(long long n, long long m, long long mod)
 79 {
 80     long long ans = 0;
 81     for(long long i = 1;i <= tot;++ i)
 82     {
 83         long long pt = fang[i];
 84         long long tmp3 = C(n, m, prime[i], pt);
 85         ans += tmp3 * (mod/pt) % mod * ni(mod/pt, pt) % mod;
 86         ans %= mod;
 87     }
 88     return ans;
 89 }
 90 long long n,m,w,p,ans = 1;
 91 int main()
 92 {
 93     read(p), read(n), read(m);fenjie(p);
 94     for(long long i = 1;i <= m;++ i) 
 95     {    
 96         read(w);
 97         if(n - w < 0)
 98         {
 99             printf("Impossible");
100             return 0;
101         }
102         ans *= exlucas(n,w,p), n -= w;
103         ans %= p;
104     }
105     printf("%lld", ans);
106     return 0;
107 }
BZOJ2142

 

posted @ 2018-02-02 21:41  嘒彼小星  阅读(282)  评论(0编辑  收藏  举报