HDU 5651

题意:

给你一个字符串,可以打乱顺序,问可以组合成几种回文串。

其实就是给你一些字母,让你组合回文串。

首先判断能不能成一个回文串,其次计算一共有几种方法。

len为奇数:只有一个字母为奇数,其余必须为偶数。

len为偶数:所有的字母都要是偶数个。

计算回文串的方法是:一共有len/2个位置可选。

运用组合数:每次从剩余的位置中选择需要的字母个数,乘起来就可以了。

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stdlib.h>
#include <queue>
using namespace std;

char a[1010];
int c[2010][2000];
int main()
{
    int T,n;
    memset(c,0,sizeof(c));
    c[0][0]=1;
    for(int i=1; i<=510; i++)
    {
        c[i][0]=1;
        for(int j=1; j<=510; j++)
        {
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%1000000007;
        }
    }
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",a);
        int len=strlen(a);
        int vis[30];
        memset(vis,0,sizeof(vis));
        for(int i=0; i<len; i++)
        {
            vis[a[i]-‘a‘]++;
        }
        int f=0;
        for(int i=0; i<26; i++)
        {
            if(vis[i]%2!=0)
            {
                f++;
            }
        }
        if(len%2==0)
        {
            if(f>0)
            {
                printf("0\n");
            }
            else
            {
                len/=2;
                long long sum=1;
                for(int i=0; i<26; i++)
                {
                    if(vis[i]!=0)
                    {
                        vis[i]/=2;
                        sum=(c[len][vis[i]]%1000000007)*(sum%1000000007);
                        sum%=1000000007;
                        len-=vis[i];
                    }
                }
                printf("%I64d\n",sum);
            }
        }
        else
        {
            if(f>1)
            {
                printf("0\n");
            }
            else if(f==1)
            {
                len/=2;
                long long sum=1;
                for(int i=0; i<26; i++)
                {
                    if(vis[i]!=0)
                    {
                        vis[i]/=2;
                        sum=(c[len][vis[i]]%1000000007)*(sum%1000000007);
                        sum%=1000000007;
                        len-=vis[i];
//                        printf("%d\n",len);
                    }
                }
                printf("%I64d\n",sum);
            }
        }
    }
    return 0;
}
时间: 2024-10-22 15:50:30

HDU 5651的相关文章

HDU 5651 xiaoxin juju needs help(BestCoder Round #77 (div.1)1001)

传送门 xiaoxin juju needs help Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 861    Accepted Submission(s): 243 Problem Description As we all known, xiaoxin is a brilliant coder. He knew **palin

HDU 5651 xiaoxin juju needs help 逆元

给你n个字母,求可以组成的回文串的个数 1.n为奇数,有一个字母的个数为奇数 2.n为偶数,字母个数全为偶数 然后将字母的个数num[i]/2,得出在对称轴左边的个项字母的个数 假设左边有len个字母,如果每个字母都不同则有len!中可能 然后除去所有重复的可能num[i]!即可 因为除法取模 (len!/num[i]!)%mod a^(p-1) = 1(mod p)p为素数    于是 a*a^(p-2) = 1(mod p)所以a^(p-2)替代1/a. 所以上面的公式  ->  len!*

hdu 5651 重复全排列+逆元

知识点: n个元素,其中a1,a2,····,an互不相同,进行全排列,可得n!个不同的排列. 若其中某一元素ai重复了ni次,全排列出来必有重复元素,其中真正不同的排列数应为 ,即其重复度为ni! 同理a1重复了n1次,a2重复了n2次,····,ak重复了nk次,n1+n2+····+nk=n. 对于这样的n个元素进行全排列,可得不同排列的个数实际上是  由于题目要求是对100000007取余 同余定理中对于同一个除数,两个数的乘积与它们余数的乘积同余.但这里有除法所以得用上逆元 逆元 定义

HDU 5651 xiaoxin juju needs help

组合数杨辉三角打表,这样避免了除法求逆元. #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> using namespace std; const long long MOD=1000000007; const int maxn=1000+10; long long c[maxn][maxn]; int tot[30]; c

HDU 5651 逆元

xiaoxin juju needs help Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 809    Accepted Submission(s): 231 Problem Description As we all known, xiaoxin is a brilliant coder. He knew **palindromi

hdu 2795 Billboard(线段树+单点更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 13050    Accepted Submission(s): 5651 Problem Description At the entrance to the un

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往