[BestCoder Round#26] Apple 【組合數學】

來源:互聯網
上載者:User

標籤:

題目連結:HDOJ - 5160

 

題目分析

第一眼看上去,要求統計所有不同排列對答案的貢獻。嗯...完全沒有想法。

但是,如果我們對每個數字單獨考慮,計算這個數字在總答案中的貢獻,就容易多了。

對於一個數字 ai ,有 ni 個 。比它大的數字有 p 個,比它小的數字有 q 個。所有的數字一共有 N 個。

首先,比它小的數字對它不會造成影響,所以我們只要考慮它和比它大的數字。那麼我們就在 N 個位置中,選 (ni + p) 個位置,給它和比它大的數字。

然後比它大的數字有 x1 種排列,比它小的數字有 x2 種排列。這個如何來求呢?這是多重集排列。

  多重集排列,對於一個多重集 A={a1*n1, a2*n2, a3*n3, ak*nk} 。排列數為 Sum(n1...nk)!/(n1!n2!n3!...nk!)

那麼 ai 有多少個會被記入答案呢?我們枚舉每種情況:有 ni 個記入答案, (ni-1) 個, (ni-2)個 .... 1 個。

如果有 k 個 ai 無法記入答案,說明有比它們大的數在他們前面,也就是說他們被插到了 p 個比他們大的數後面或之間。這 p 個數後面一共有 p 個位置,每個位置都可以插入任意個 ai ,這種情況數為 C(k + p - 1, k) (相當於向 p 個箱子裡分配 k 個球,隔板法)。

那麼 ai 對答案的貢獻就為 C(N, ni + p) * x1 * x2 * sigma((ni - k) * C(k + p - 1, k)) (0 <= k < ni) * ai 。

 

Warning!

出現的錯誤: % 的優先順序比 + 高!如果這樣 Ans = Ans + temp % Mod 。Ans 是會爆掉的!!應該是 Ans = (Ans + Temp) % Mod 。

昨天晚上因為這個錯誤debug了3hours!!!!!! 

 

代碼
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int MaxN = 100000 + 15; typedef long long LL;const LL Mod = 1000000007ll;int T, n, Top;LL Ans;LL A[MaxN], f[MaxN], g[MaxN], Sum[MaxN], NSum[MaxN], Fac[MaxN], NY_Fac[MaxN];struct ES_Num{    LL Cnt, Num;    ES_Num() {}    ES_Num(LL a, LL b) {        Num = a; Cnt = b;    }} ES[MaxN];LL Pow(LL a, LL b) {    LL f, ret;    f = a; ret = 1ll;    while (b) {        if (b & 1) {            ret *= f;            ret %= Mod;        }        b >>= 1;        f *= f;        f %= Mod;    }    return ret;}void Init() {    int Max_Num = 100000 + 5;    Fac[0] = 1;    for (int i = 1; i <= Max_Num; ++i)         Fac[i] = Fac[i - 1] * i % Mod;    for (int i = 0; i <= Max_Num; ++i)         NY_Fac[i] = Pow(Fac[i], Mod - 2);}LL C(LL a, LL b) {    if (b == 0) return 1;    if (a < b) return 0;    LL ret;    ret = Fac[a];    ret = ret * NY_Fac[a - b] % Mod;    ret = ret * NY_Fac[b] % Mod;    return ret;}int main() {    Init();    scanf("%d", &T);    for (int Case = 1; Case <= T; ++Case) {        scanf("%d", &n);        Ans = 0;        for (int i = 1; i <= n; ++i) scanf("%d", &A[i]);        sort(A + 1, A + n + 1);        Top = 0;        for (int i = 1; i <= n; ++i) {            if (i != 1 && A[i] == A[i - 1]) ++(ES[Top].Cnt);            else ES[++Top] = ES_Num((LL)A[i], 1);        }        Sum[0] = 0;        for (int i = 1; i <= Top; ++i)             Sum[i] = Sum[i - 1] + ES[i].Cnt;        NSum[Top + 1] = 0;        for (int i = Top; i >= 1; --i)             NSum[i] = NSum[i + 1] + ES[i].Cnt;        LL t = 1;        f[0] = 1;        for (int i = 1; i <= Top; ++i) {            t = t * Fac[Sum[i]] % Mod * NY_Fac[ES[i].Cnt] % Mod;            f[i] = t;            t = t * NY_Fac[Sum[i]] % Mod;        }        t = 1;        g[Top + 1] = 1;        for (int i = Top; i >= 1; --i) {            t = t * Fac[NSum[i]] % Mod * NY_Fac[ES[i].Cnt] % Mod;            g[i] = t;            t = t * NY_Fac[NSum[i]] % Mod;        }        LL x, y;        for (int i = 1; i <= Top; ++i) {            x = 0;            for (int j = 0; j < ES[i].Cnt; ++j) {                y = (ES[i].Cnt - j) * C(NSum[i + 1] + j - 1, j) % Mod;                x = (x + y) % Mod;            }            x = x * ES[i].Num % Mod;            x = x * f[i - 1] % Mod;            x = x * g[i + 1] % Mod;             x = x * C(NSum[1], NSum[i]) % Mod;            Ans = (Ans + x) % Mod;        }        printf("Case #%d: %d\n", Case, (int)Ans);    }    return 0;}

  

[BestCoder Round#26] Apple 【組合數學】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.