HDU - 1261 字串数 多重集合的排列问题+高精度

题目链接


题意:

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

计算一共可以组成多少个不同的字符串.


思路:

  这个算是一个水题了,直接套多重集合排列的公式,这个公式也只适用于当r==n的情况.

公式为:

n!/(n1!*n2!*n3!....nk!)    n为所有字母的和.

   上述可以理解成,n个位置,第一个位置n个选法,第2个(n-1)个,.....到最后就是n!个选法,对于每个集合ni,进行去重,就得到了上述的公式.


但是这个题,每个字母最多12,直接算存不下,只能用大数来模拟了.

#include
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define exp 0.00000001
#define  pii  pair
#define  mp   make_pair
#define  pb   push_back
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int base=100000;
int num[1111];
int n,a[30];
int main()
{
	while(~Ri(n))
	{
		if(n==0)
		break;
	int s=0;
	for(int i=1;i<=n;i++)
	{
		Ri(a[i]);
		s+=a[i];
	}
	CLR(num,0);
	num[0]=1;
	int car=0;
	int len=1;
	for(int i=2;i<=s;i++)
	{
		car=0;
		for(int j=0;j=base)
			{
				car=num[j]/base;
				num[j]%=base;
			}
			else
			car=0;
		}
		if(car!=0)
		num[len++]=car;
	}
	int res=0;
//	int w;
	for(int i=1;i<=n;i++)
	{
		for(int j=2;j<=a[i];j++)
		{
			for(int k=len-1;k>=0;k--)
			{
				res=num[k]+res*base;
				num[k]=res/j;
				res=res%j;
			}
		}
	}
	int item=-1;
	int flag=0;
	for(int i=1000;i>=0;i--)
	{
		if(num[i]!=0)
		{
			item=i;
			break;
		}
	 } 
	 for(int i=item;i>=0;i--)
	 {
	 	if(!flag)
	 	printf("%d",num[i]),flag=1;
	 	else
	 	printf("%05d",num[i]);
	 }
	 puts("");
	}
 return 0;
}



 

你可能感兴趣的:(组合数学,hdu,基础题)