看了题解后才会的:
If you generate all permutation of given string then you got TL, You can easily solve this problem using the formula : n! / (r1! * r2! * r3!...) Here n = total character, r1, r2, r3..= number of repeated character. Suppose aabbbc, n=6, r1=2, r2=3
Example:
Input: dcaba
1. For string dcaba. Take the first character d, find all characters are less than d. Here the characters are a, b, c.
For character a, you can find 24 possible arrangement. Because without a the string is: dcba so, 4! = 24.
For character b, you can find 12 possible arrangement. Because without b the string is: dcaa so, 4! / 2! = 12.
For character c, you can find 12 possible arrangement. Because without c the string is: daba so, 4! / 2! = 12.
Then remove the first character from "dcaba". You got "caba".
2. For string caba. Take the first character c, find all characters are less than c. Here the characters are a, b.
For character a, you can find 6 possible arrangement. Because without a the string is: cba so, 3! = 6.
For character b, you can find 3 possible arrangement. Because without b the string is: caa so, 3! / 2! = 3.
Then remove the first character from "caba". You got "aba"
3. For string aba. Take the first character a, find all characters are less than a. Here no character found.
Then remove the first character from "aba". You got "ba"
4. For string ba. Take the first character b, find all character are less than b. Here the character is a.
For character a, you can find 1 possible arrangement. Because without a the string is: b so, 1! = 1.
Remove the first character from "ba". You got "a".
Do not need to do anything for that.
Total arrangement: 24 + 12 + 12 + 6 + 3 + 1 = 58
So, 58 possible arrangement before come "dcaba". "dcaba" is the 59th arrangement.
You can do this recursively.
转自:http://www.outsbook.com/uva/?page=latest_post&category=-1&id=153
计算阶乘的话必须约分,不然会溢出,30
!太大.
#include <iostream>
#include <memory.h>
#include <cstdio>
#include <map>
#include <string>
using namespace std;
#define MAX 50
long long permutaion_repeated(string & str,map<char,int> & m){
int denominators[MAX]={0},index=0;
map<char,int>::iterator it=m.begin();
for (;it!=m.end();++it)
{
while (it->second)
{
denominators[index++]=it->second--;
}
}
long long n=1,d=1;
for (int i=1;i<=str.size();++i)
{
n*=i;
if(index>0){
d*=denominators[--index];
}
if(d!=1&&!(n%d)){
n/=d;
d=1;
}
}
return n;
}
int main(){
string str;
while (cin>>str,str!="#")
{
long long ans=1;
for (int i=0;i<str.size();++i)
{
map<char,int>m;
for (int j=i+1;j<str.size();++j)
{
if(str[j]<str[i])m[str[j]]++;//统计小于str[i]的字符
}
map<char,int>::iterator it;
for (it=m.begin();it!=m.end();++it)
{
int j;
for (j=i+1;j<str.size()&&str[j]!=it->first;++j);
string temp(str.begin()+i,str.end());
temp.erase(temp.begin()+(j-i));
map<char,int>mt;
for (j=0;j<temp.size();++j)//统计各个字母出现的次数
{
mt[temp[j]]++;
}
ans+=permutaion_repeated(temp,mt);
}
}
printf("%10lld\n",ans);
}
}