hdu 1261

字串數

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1430    Accepted Submission(s): 257


Problem Description
一個A和兩個B一共可以組成三種字符串:"ABB","BAB","BBA".
給定若干字母和它們相應的個數,計算一共可以組成多少個不同的字符串.
 

Input
每組測試數據分兩行,第一行爲n(1<=n<=26),表示不同字母的個數,第二行爲n個數A1,A2,...,An(1<=Ai<=12),表示每種字母的個數.測試數據以n=0爲結束.
 

Output
對於每一組測試數據,輸出一個m,表示一共有多少種字符串.
 

Sample Input
2 1 2 3 2 2 2 0
 

Sample Output
3 90
 

Source
 

Recommend
JGShining
 


(a1+a2+ ... +an)! / a1! / a2! / ... / an!

主要還是寫高精度!


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>

#define LEN 1500

void Sub (int *, int *);
void Mult (int *, int *);
void Div (int *, int *);
void Put (int *);
bool Smaller (int *, int *);
void Shift (int *, int);

void Mult (int *a, int *b) {
    int s = LEN;
    while (--s >= 0 && !a[s]) {}

    int t = LEN;
    while (--t >= 0 && !b[t]) {}

    int c[LEN];
    memset (c, 0, sizeof (c));
    for (int i=0; i<=s; ++i) {
        for (int k=0; k<=t && i+k<LEN; ++k) {
            c[i + k] += a[i] * b[k];
        }
    }
    int car = 0;
    for (int i=0; i<LEN; ++i) {
        int t = car + c[i];
        c[i] = t % 10;
        car = t / 10;
    }
    assert (car == 0);
    memcpy (a, c, sizeof (c));
}

void Put (int *a) {
    int i = LEN;
    while (--i > 0 && !a[i]) {}
    while (i >= 0) {
        printf ("%d", a[i--]);
    }
    printf ("\n");
}

bool Smaller (int *a, int *b) {
    for (int i=LEN-1; i>=0; --i) {
        if (a [i] > b [i]) {
            return false;
        } else if (a [i] < b [i]) {
            return true;
        }
    }
    return false;
}

void Shift (int *a, int sh) {
    if (sh < 0) {
        sh = -sh;
        for (int i=0; i<LEN-sh; ++i) {
            a[i] = a[sh + i];
        }
        for (int i=LEN-sh; i<LEN; ++i) {
            a[i] = 0;
        }
    } else if (sh > 0) {
        for (int i=LEN-1; i>=sh; --i) {
            a[i] = a[i - sh];
        }
        for (int i=sh-1; i>=0; --i) {
            a[i] = 0;
        }
    }
}

void Div (int *a, int *d) {
    int i = LEN;
    while (--i >= 0 && !a[i]) {}

    int k = LEN;
    while (--k >= 0 && !d[k]) {}

    if (i < k) {
        memset (a, 0, sizeof (a));
        return;
    }

    Shift (d, i - k);

    static int res[LEN];
    memset (res, 0, sizeof (res));

    i -= k;
    while (i >= 0) {
        while (! Smaller (a, d)) {
            Sub (a, d);
            ++res[i];
        }
#ifdef _DEBUG
        printf ("\n");
        Put (a);
        Put (d);
        Put (res);
#endif
        --i;
        Shift (d, -1); // divided by 10 (the radix)
    }

    memcpy (d, a, sizeof (*a) * LEN);
    memcpy (a, res, sizeof (res));
}

void Sub (int *a, int *b) {
    int bor = 0; // borrow
    for (int i=0; i<LEN; ++i) {
        int t = a[i] - b[i] - bor;
        a[i] = (t + 10) % 10;
        bor = 1 - (t + 10) / 10;
    }
    assert (bor == 0);
}

#define FACS 320

int fac[FACS][LEN];

int main () {
    memset (fac, 0, sizeof (fac));
    fac[0][0] = 1;
    for (int i=1; i<FACS; ++i) {
        fac[i][0] = i % 10;
        fac[i][1] = i / 10 % 10;
        fac[i][2] = i / 100;
        Mult (fac[i], fac[i - 1]);
#ifdef _DEBUG
        Put (fac[i]);
#endif
    }
    int n;
    while (scanf ("%d", &n) == 1 && n) {
        static int a[100];
        int sum = 0;
        for (int i=0; i<n; ++i) {
            scanf ("%d", &a[i]);
            sum += a[i];
        }
        static int res[LEN];
        memcpy (res, fac[sum], sizeof (res));
        static int div[LEN];
        memset (div, 0, sizeof (div));
        div[0] = 1;
        for (int i=0; i<n; ++i) {
            Mult (div, fac[a[i]]);
        }
        Div (res, div);
        Put (res);
    }
    return 0;
}


發佈了94 篇原創文章 · 獲贊 1 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章