xiaoxin juju needs help
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 594 Accepted Submission(s): 175
Problem Description
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?
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)
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) .
For each test case, there is a single line containing a string 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,007
.
Sample Input
3 aa aabb a
Sample Output
1 2 1
Source
无语了,求杨辉三角居然忘了注意边界C(n, 0) = 1,求的时候取模还不彻底,无语......失之毫厘谬以千里......
思路主要就是判断字符串长度的奇偶性,结合每个元素的奇偶性来判断有没有可能组成回文
如果可以的话然后利用组合数来算有多少种
比如
cccbba a abbccc
len = 13 但是实际上只要算len / 2 = 6也就是黑体的这一半的组合情况就行了,另外一半对称
算法是,如果取a,b,c的顺序,那么对于a:C(6, 1),对于b去掉a占的位置:C(6 - 1, 2) = C(5, 2)
对于c去掉b, a占得位置:C(6 - 1 - 2, 3) = C(3, 3)
根据乘法原理ans = C(6, 1) * C(5, 2) * C(3, 3)
偶数情况以此类推
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
using namespace std;
long long mod = 1000000007;
char ch[1005];
long long c[1005][1005];
map<char, int> m;
//用记忆化搜索来求杨辉三角,记忆数组c
long long C(int n, int m) {
if (n == m || m == 0) return 1; //注意边界
if (c[n][m] != -1) {
return c[n][m] % mod; //注意取模
}
return c[n][m] = (C(n - 1, m) + C(n - 1, m - 1)) % mod; //注意取模
}
int main()
{
int T;
//c是通用的直接放最外面就行
memset(c, -1, sizeof(c));
c[0][0] = 1;
c[1][0] = 1; c[1][1] = 1;
c[2][0] = 1; c[2][1] = 2; c[2][2] = 1;
scanf("%d", &T);
while (T--) {
m.clear();
scanf("%s", ch);
int len = strlen(ch);
for (int i = 0; i < len; i++) {
m[ch[i]]++; //散列计数,其实直接开个数组也行
}
if (len == 1) {
puts("1");
continue;
}
//算奇数的个数
int ji = 0;
for (map<char, int>::iterator i = m.begin(); i != m.end(); i++) {
if (i->second % 2) {
ji++;
}
}
long long ans = 1;
//能算的情况是没有奇数,而且字符串的长度为偶数,或者有且仅有一个奇数字符串长度也为奇数
//否则不可能构成回文
if ((ji == 0 && len % 2 == 0) || (ji == 1 && len % 2 != 0)) {
//只需要计算一般的情况就可以了,因为另外一般是对称的
len /= 2;
for (map<char, int>::iterator i = m.begin(); i != m.end(); i++) {
i->second /= 2;
}
for (map<char, int>::iterator i = m.begin(); i != m.end(); i++) {
ans = (ans * (C(len, i->second) % mod)) % mod; //注意取模
len -= i->second;
}
}
else {
puts("0");
continue;
}
printf("%I64d\n", ans);
}
return 0;
}