• 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的

    公式: 

    $inom n {w_1}+inom {n-w_1} {w_2}+inom {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
  • 相关阅读:
    贫血,充血模型的解释以及一些经验(非常经典)(非原创)
    源代码管理安装大全
    20条常见的编码陷阱 你中枪了没?(转)
    从30岁到35岁:为你的生命多积累一些厚度(转)
    Model1 与Model2(转)
    白话MVP(转帖)
    stl string 使用
    TerminateThread不要使用的證據
    C++静态成员函数小结(转)
    C/C++必知必会1
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8407119.html
Copyright © 2020-2023  润新知