HDU5651:xiaoxin juju needs help

HDU5651:xiaoxin juju needs help

    • 题目大意
    • 思路
    • 代码

题目大意

传送门
现在给你一个字符串,进行随机排序,求最后有多少种情况是回文串

思路

实际上,我们可以知道,如果奇数次出现的字符大于等于2个,那这个字符串就凉了。我们可以设每个字符的出现次数为 t o t [ i ] tot[i] tot[i],那么,就相当于求 ( t o t [ i ] > > = 1 ) (tot[i]>>=1) (tot[i]>>=1)组成的多重集的排列数,为什么呢?就相当于把字符串分成两半,两边一样,然后这个东西有个公式,叫做:对于一个多重集{ a 1 × s 1 , a 2 × s 2 , … … , a k × s k a_1\times s_1,a_2\times s_2,……,a_k\times s_k a1×s1,a2×s2,,ak×sk},其中, s i s_i si是第i个元素, a i a_i ai是第i个元素的个数,则 a n s = n ! ∏ i = 1 k a i ! ans=\frac{n!}{\prod_{i=1}^{k}a_i!} ans=i=1kai!n!,其中, n = ∑ i = 1 k a i n=\sum_{i=1}^{k}a_i n=i=1kai,所以我们就可以直接算出来了

代码

#include 
#include 
#include 
#include 
#include  
using namespace std;

#define Int register int
#define mod 1000000007
#define int long long
#define MAXX 1005
#define MAXN 30

int num[MAXN];
int inv[MAXX],fac[MAXX],inv_fac[MAXX];

string s;

void init()
{
	fac[0] = inv[1] = inv_fac[1] = inv_fac[0] = 1;
	for (Int i = 1;i <= 1000;++ i)
	{
		fac[i] = fac[i - 1] * i % mod;
		if(i > 1)
		{
			inv[i] = inv[mod % i] * (mod - mod / i) % mod;
			inv_fac[i] = inv_fac[i - 1] * inv[i] % mod;
		}
	}
}

int C(int n,int m)
{
	if(n < m) return 0;
	else if(n < 0 || m < 0) return 0;
	else return fac[n] * inv_fac[m] % mod * inv_fac[n - m] % mod; 
}

void read (int &x)
{
	x = 0;char c = getchar();int f = 1;
	while(c < '0' || c > '9'){if(c == '-')f = -f;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + c - '0';c = getchar();}
	x *= f;return ;
}

void write (int x)
{
	if (x < 0){x = -x;putchar('-');}
	if (x > 9) write (x / 10);
	putchar (x % 10 + '0');
}

signed main()
{
	init();	
	int times;
	read (times);
	while (times --)
	{
		memset (num,0,sizeof (num));
		cin >> s;
		int sum = 0;
		bool flag = 1,cant = 1;
		for (Int i = 0;i < s.length();++ i)
			num[s[i] - 'a'] ++;
		for (Int i = 0;i < 26;++ i)
		{
			if (num[i] % 2)
			{
				if (!flag)
				{
					cant = 0;
					break;
				}
				flag = 0;
			}
			num[i] >>= 1;
			sum += num[i];
		}
		if (!cant)
		{
			puts ("0");
			continue;
		}
		int ans = fac[sum];
		for (Int i = 0;i < 26;++ i)
			ans = (ans * inv_fac[num[i]] % mod) % mod;
		write (ans),putchar ('\n');
	}
	return 0;
}

你可能感兴趣的:(数论,思维题,组合数学)