Hdu-1261 字串數
阿新 • • 發佈:2019-01-02
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
問題分析:
不難看出是有重複元素的排列問題。
sum = a1 + a2 + … + an;
公式 result = sum! / (a1 ! * a2 ! * … * an !);
但是,sum的最大值已經是300多了,肯定是高精度運算。
下面的程式碼:思路很簡單,先求出sum!再除a1到an的階乘。不過需要選擇適當的模板,ai的範圍是[1,12],所以除法的話用的是高精度除以單精度,是O(n)的演算法,乘法是自己寫的一個模板,複雜度是O(n^2), 下面的程式碼是AC的。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
string mul(string a, string b)
{
int len = a.size() + b.size();
vector<int> res(len, 0);
for (int i = 0; i < a.size(); i++)
{
for (int j = 0; j < b.size(); j++)
{
res[j + i] += (a[i] - '0') * (b[j] - '0');
}
}
string tmpres = "";
int i = res.size() - 2;
int r = 0;
while (i >= 0){
int t = res[i] + r;
tmpres = (char)(t % 10 + '0') + tmpres;
r = t / 10;
i--;
}
while (r){
tmpres = (char)(r % 10 + '0') + tmpres;
r = r / 10;
}
return tmpres;
}
string div(string a, ll b)//高精度a除以單精度b
{
string r, ans;
ll d = 0;
if (a == "0") return a;//特判
for (int i = 0; i<a.size(); i++)
{
r += (d * 10 + a[i] - '0') / b + '0';//求出商
d = (d * 10 + (a[i] - '0')) % b;//求出餘數
}
ll p = 0;
for (int i = 0; i<r.size(); i++)
if (r[i] != '0') { p = i; break; }
return r.substr(p);
}
ll get_n_i(int a)
{
ll res = 1;
for (int i = 2; i <= a; i++)
res *= i;
return res;
}
int main()
{
int n;
while (cin >> n, n)
{
vector<ll> nums(30);
int m = 0;
for (int i = 0; i < n; i++){
cin >> nums[i];
m += nums[i];
nums[i] = get_n_i(nums[i]);
}
string tmpa = "1";
for (int i = 2; i <= m; i++){
tmpa = mul(tmpa, to_string(i));
}
for (int i = 0; i < n; i++){
tmpa = div(tmpa, nums[i]);
}
cout << tmpa << endl;
}
}