2 1 2 3 2 2 2 0
3 90
全排列知识:考虑n个元素组成的多重集,其中a1重复了n1次,a2 重复了n2次,…,ak重复了nk次,n=n1+n2+…+nk。
考虑n个元素的全排列,则不同的排列数为:n!/(n1!*n2!*n3!……nk!);
题意:
给定若干字母和它们相应的个数,计算一共可以组成多少个不同的字符串.
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MAX=100; const int B=10000; int fa[285][MAX],ans[MAX]; //计算阶乘 void f(int str[],int maxn,int x){ int i,carry=0; for(i=maxn-1;i>=0;i--){ carry+=str[i]*x; str[i]=carry%B; carry/=B; } } //大数相除 void devide(int str[],int x,int maxn){ int i,carry=0; for(i=0;i<maxn;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]=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--) devide(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; }