xiaoxin juju needs help

As we all known, xiaoxin is a brilliant coder. He knew palindromic strings when he was only a six grade student at elementry school.

This summer he was working at Tencent as an intern. One day his leader came to ask xiaoxin for help. His leader gave him a string and he wanted xiaoxin to generate palindromic strings for him. Once xiaoxin generates a different palindromic string, his leader will give him a watermelon candy. The problem is how many candies xiaoxin’s leader needs to buy?
Input
This problem has multi test cases. First line contains a single integer T(T≤20)T(T≤20) which represents the number of test cases.
For each test case, there is a single line containing a string S(1≤length(S)≤1,000)S(1≤length(S)≤1,000).
Output
For each test case, print an integer which is the number of watermelon candies xiaoxin’s leader needs to buy after mod 1,000,000,0071,000,000,007.

Sample Input

3
aa
aabb
a
Sample Output

1
2
1

此题 应用 组合数 排列 中 带有重复的 字符串的 全排列 问题

for example :

有 你个 小球 其中 m 个 小球 是相同的 , 那么 这 n 个小球 的 全排列 为 !n / !m ;

整体思路 先用 一个 整形数组 和 map 将字符串里 的 不同的字符 进行编号 ,数组 用来储存 相同编号 所对应 的字符 的 个数 , 数组 的下标 即 对应 字符 的编号, 然后 分 总字符数 的 奇 和 偶 分别 考虑
先判断 该字符串 是否满足 可以组成回文串 的 条件 (奇 与 偶 的判断条件 不同 ) 然后进行 公式 计算 其中 还采用了 乘法逆元 防止 被除数 过大 导致 精度损失 太大 ;
详细 见代码
代码如下

#include <cstring>
#include <algorithm>
#include <map>
#define mod 1000000007
#define LL long long
using namespace std;

LL pows[600];
void F()
{
    pows[0] = 1;
    LL num = 1;
    for(int i = 1; i < 510; i++)
    {
        num *= i;
        num %= mod;
        pows[i] = num;
    }
}

LL quick_pows(LL a, LL b)
{
    LL ret = 1;
    LL temp = a;
    while(b)
    {
        if(b & 1) ret = ret * temp % mod;
        temp = temp * temp % mod;
        b /= 2;
    }

    return ret;
}

int main()
{
    F();
    int t;
    scanf("%d", &t);
    getchar();// 去空格

    while(t--)
    {
        int len;
        int arr[1010];// 存储 字符串
        char str[1010];// 存储 字符出现的次数
        map<char, int> sky;

        gets(str);
        len = strlen(str);
        sky.clear();
        memset(arr, 0, sizeof(arr));

        int num = 1;// 为 字符 编号 
        for(int i = 0; i < len; i++)
        {
            char ch = str[i];
            if(!sky[ch])// 如果 该字符没有出现过
            {
                sky[ch] = num++;// 则对该字符 编号
                arr[sky[ch]]++;
            }
            else
                arr[sky[ch]]++;
        }

        int kind, group = 0; // group 存储 字符 对 的 对数
        kind = num - 1;// 字符 的种类 数

        for(int i = 1; i <= kind; i++)
            group += arr[i]/2;

        LL a, b = 1, ans;
        if(len % 2 == 0)
        {
            if(group*2 != len) printf("0\n");
            else
            {
                for(int i = 1; i <= kind; i++)
                {
                    b *= pows[arr[i] / 2];
                    b %= mod;
                }

                a = pows[group];
                ans = a * quick_pows(b, mod-2) % mod;// 采用 乘法逆元  将a/ b % mod => a*(b关于 mod 的逆元)% mod
                printf("%lld\n", ans);
            }
        }
        else
        {
            if(group*2 != len-1) printf("0\n");
            else
            {
                for(int i = 1; i <= kind; i++)
                {
                    b *= pows[arr[i]/2];
                    b %= mod;
                }

                a = pows[group];
                ans = a * quick_pows(b, mod-2) % mod;
                printf("%lld\n", ans);
            }
        }


    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值