Palindrome number

回文字符串:

=============Question================

Now that the king knows how to find out whether a given word has an anagram which is a palindrome or not, he is faced with another challenge. He realizes that there can be more than one anagram which are palindromes for a given word. Can you help him find out how many anagrams are possible for a given word which are palindromes?

    The king has many words. For each given word, the king needs to find out the number of anagrams of the string which are palindromes. As the number of anagrams can be large, the king needs number of anagrams % (10^9+ 7).

    Input format :
    A single line which will contain the input string

    Output format :
    A single line containing the number of anagram strings which are palindrome % (10^9 + 7).

    Constraints :

        1<=length of string <= 105
        Each character of the string is a lowercase alphabet.
        Each testcase has atleast 1 anagram which is a palindrome.

    Sample Input 01 :
    aaabbbb
    Sample Output 01 :
    3 

    Explanation :
    Three permutation of given string which are palindrome can be given as abbabba , bbaaabb and bababab.

    Sample Input 02 :

    cdcdcdcdeeeef

    Sample Output 02 :


    90

=============================

很明显如果字符串中某个字符出现次数为奇数,则该字符必须出现在整个串的中间,才有可能让整个串为回文。如果有两个或超过两个的串为奇数,则整个串必不回文。

既然整个串为回文,我们只需要对称考虑一边字符串的组合数,就可以知道对给定字符串有多少回文组合。

这个问题转化为求回文字符串一侧的组合数,其实是计算

p! / (x! y! z! ... n!)

p为所有不同的字符除以2以后的综合,x,y...,n是每个不同的字符除以2以后的值。

这个数字可能非常大,必须小心溢出,这就是为什么要模1000000007了。即便如此,这个计算该怎么进行呢?

参考http://comeoncodeon.wordpress.com/category/algorithm/提供的算法,可以很方便的计算。

        /* This function calculates (a^b)%MOD */
	unsigned long long pow(unsigned long long a, unsigned long long b, unsigned long long MOD)
	{
		unsigned long long x = 1;
		if (b == 0) {
			return 1;
		}
		if (b == 1) {
			if (a > MOD) {
				return a%MOD;
			}
			return a;
		}
		x = pow(a, b >> 1, MOD);
		x = x*x;
		if (x > MOD) {
			x %= MOD;
		}

		if ((b & 0x1) == 1) {
			x = x * a;
			if (x > MOD) {
				x %= MOD;
			}
		}
		return x;
	}
 
	/*  Modular Multiplicative Inverse
            Using Euler's Theorem
            a^(phi(m)) = 1 (mod m)
            a^(-1) = a^(m-2) (mod m) */
	unsigned long long InverseEuler(unsigned long long n, unsigned long long MOD)
	{
		return pow(n,MOD-2,MOD);
	}

	unsigned long long factorial(int total, unsigned short count[], int len) {
		unsigned long long vec[51];
		vec[0] = 1;
		for (int i = 1; i < 51; i++) {
			vec[i] = (vec[i-1] * i) % PRIME;
		}
		unsigned long long result = 0;
		for (int i = 0; i < len; i++) {
			int c = count[i];
			if (c != 0) {
				if (result == 0) {
					result = InverseEuler(vec[c], PRIME);
				} else {
					result = (InverseEuler(vec[c], PRIME) * result) % PRIME;
				}
			}
		}
		return (vec[total] * result) % PRIME;
	}

        int palindrome(const string& s) {
		unsigned short count4allchar[CHAR_NUM];
		int i = 0;
		for (i = 0; i < CHAR_NUM; i++) {
			count4allchar[i]=0;
		}
		
		for (string::const_iterator iter = s.begin(); 
			iter != s.end(); iter++) {
			char c = *iter;
			count4allchar[c - 'a']++;
		}
		// if there are more than one odd in the string, return 0,
		// otherwise, count the number of even number and save the even/2 number back
		int oddCount = 0;
		int total = 0;
		for (i = 0; i < CHAR_NUM; i++) {
			int num = count4allchar[i];
			if (num != 0) {
				if ((num & 0x1) == 1) {
					oddCount++;
					if (oddCount > 1) {
						return 0;
					}
				}
				count4allchar[i] = num >> 1; // div 2
				total += count4allchar[i];
			}
		}
		// 
		int result = factorial(total, count4allchar, CHAR_NUM);
		return result;
	}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值