题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1261
题目解析:
有n个不同字符,每个字符次数为 A1, A2, … An;
如果不考虑重复字符数,那不同的字串个数就是∑(An)个字符的全排列
再除以重复的 A1到An各自全排列之和。
本题关键是全排列过程中整数范围会超过int或者long long的范围,需要用数组存储大整数自行实现大整数的乘除
#include<iostream>
using namespace std;
/* An / sigma Ai */
int num[26], res[1000], len = 0;
// res数组存的是大整数各位的数字,高位在前,方便扩展位和缩位
// sortRes函数是将数组res里存的大整数转成十进制,把每一位大于9的进位
void sortRes() {
for (int i = 0; i < len; i++) {
if (res[i] > 9) {
if (i == len - 1) {
len++; //扩展一位
}
res[i + 1] += res[i] / 10;
res[i] = res[i] % 10;
}
}
}
//函数A是计算全排列
void A(int n) {
res[0] = n;
len = 1;
while (--n > 0) {
for (int i = 0; i < len; i++) {
res[i] *= n;
}
sortRes();
}
}
//大整数除法
void divideRes(int n) {
for (int i = len - 1; i >= 0; i--) {
if (res[i] < n) {
if (i == len - 1) {
len--; //缩一位
}
res[i - 1] += res[i] * 10;
res[i] = 0;
} else {
if (i > 0) {
res[i - 1] += (res[i] % n) * 10;
}
res[i] = res[i] / n;
}
}
}
int main() {
int n;
while (1) {
cin >> n;
if (n == 0) {
break;
}
memset(num, 0, sizeof(num));
memset(res, 0, sizeof(res));
long long total = 0; //total是字符个数总数
for (int i = 0; i < n; i++) {
cin >> num[i];
total += num[i];
}
A(total);
for (int i = 0; i < n; i++) {
for (int j = 2; j <= num[i]; j++) {
divideRes(j);
}
}
for (int i = len - 1; i >= 0; i--) {
cout << res[i];
}
cout << endl;
}
}