字串数

题目描述

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

输入

每组测试数据分两行,第一行为n(1<=n<=26),表示不同字母的个数,第二行为n个数A1,A2,...,An(1<=Ai<=12),表示每种字母的个数.测试数据以n=0为结束.

输出

对于每一组测试数据,输出一个m,表示一共有多少种字符串.

样例输入

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!);

题意:

一个A和两个B一共可以组成三种字符串:"ABB","BAB","BBA".

给定若干字母和它们相应的个数,计算一共可以组成多少个不同的字符串.


#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;
}


  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值