组合数学 + 大数乘法 + 大数除法 之 hdu 1261 字串数

//  [3/17/2015 JmingS]
/*
此题可直接推导出公式:
	{(A1+A2+……+An)!} / {A1!A2!……An!}

由于 (12×26)! = 312! 只能通过数组来存储,所以又涉及『大数乘法』和『大数除法』,
大数实现的主要思想模拟手算,具体参考程序。
 
*/
 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6 const int MAX = 800;
 7 
 8 int n, arr[30];
 9 int total;
10 int Ans[MAX], len;
11 
12 // 阶乘
13 void Factorial(int _n, int _arr[], int &_len) {
14     for (int num = 2; num <= _n; ++num) {
15         int cnt = 0, val, carry = 0;
16         for (; cnt < _len; ++cnt) {
17             val = _arr[cnt] * num + carry;
18             _arr[cnt] = val % 10;
19             carry = val / 10;
20         }
21         while (carry) {
22             _arr[_len++] = carry % 10;
23             carry /= 10;
24         }
25     }
26 }
27 
28 // 大数除法
29 void Div(int data) {
30     int carry = 0;
31     int val;
32     for (int i = len - 1; i >= 0; --i) {
33         val = Ans[i] + carry * 10;
34         Ans[i] = val / data;
35         carry = val%data;
36     }
37     while (0 == Ans[len - 1]) {
38         --len;
39     }
40 }
41 
42 void Solve() {
43     for (int i = 0; i < n; ++i) {
44         for (int j = 2; j <= arr[i]; ++j) {
45             Div(j);
46         }
47     }
48 }
49 
50 int main()
51 {
52     //freopen("input.txt", "r", stdin);
53     //freopen("output.txt", "w", stdout);
54     while (~scanf("%d", &n) && n) {
55         total = 0;
56         for (int i = 0; i < n; ++i) {
57             scanf("%d", &arr[i]);
58             total += arr[i];
59         }
60         Ans[0] = 1;
61         len = 1;
62         Factorial(total, Ans, len);
63         Solve();
64         for (int i = len - 1; i >= 0; --i) {
65             printf("%d", Ans[i]);
66         }
67         printf("\n");
68     }
69     return 0;
70 }

 



posted @ 2015-03-18 00:09  JmingS  阅读(249)  评论(0编辑  收藏  举报