HDU1261字串数(全排列)

全排列知识:考虑n个元素组成的多重集,其中a1重复了n1次,a2 重复了n2次,…,ak重复了nk次,n=n1+n2+…+nk。

                         考虑n个元素的全排列,则不同的排列数为:n!/(n1!*n2!*n3!……nk!);

题意:

一个A和两个B一共可以组成三种字符串:"ABB","BAB","BBA".
给定若干字母和它们相应的个数,计算一共可以组成多少个不同的字符串.
 原题链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1261

题解:用大数相乘与大数相除,然后带入公式;即可解出;

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int MAX=100;
const int B=10000;
int fa[285][MAX],ans[MAX];
void f(int str[],int MAx,int x)//计算阶乘
{
    int i,carry=0;
    for(i=MAx-1;i>=0;i--)
    {
        carry+=str[i]*x;
        str[i]=carry%B;
        carry/=B;
    }
}
void divide(int str[],int x,int MAx)//大数相除
{
    int i,carry=0;
    for(i=0;i<MAx;i++)
    {
        carry=carry*B+str[i];
        str[i]=carry/x;
        carry%=x;
    }
}
void init()//初始化
{
    int i;
    memset(fa[0],0,MAX*sizeof(int));
    fa[0][MAX-1]=1;
    fa[1][MAX-1]=1;
    for(i=2;i<285;i++)
    {
        memcpy(fa[i],fa[i-1],MAX*sizeof(int));
        f(fa[i],MAX,i);
    }
}
void output(int c[],int sum,int n)//输出
{
    int i,j;
    memcpy(ans,fa[sum],MAX*sizeof(int));
    for( i=0;i<n;i++)
    {
        for( j=c[i];j>0;j--)
       divide(ans,j,MAX);
    }
   for(i=0;ans[i]==0&&i<MAX;i++);
   cout<<ans[i++];
   for(;i<MAX;i++)
   printf("%04d",ans[i]);//控制输出错误
   printf("\n");
}
int main()
{
    init();
    int i,j,k,n,c[27];
    while(scanf("%d",&n),n!=0)
    {
        int sum=0;
        memset(ans,0,MAX*sizeof(int));
        for( i=0;i<n;i++)
        {
            scanf("%d",&c[i]);
            sum+=c[i];
        }
        output(c,sum,n);
    }
   return 0;
}


你可能感兴趣的:(排列组合)