hdu 5651 组合数学+费马小定理求逆元
2016-04-22 13:24
323 查看
http://acm.hdu.edu.cn/showproblem.php?pid=5651
给定字符串,判断任意交换顺序,能产生几个回文串。
先判定0,如果有超过一个字母出现的次数那么就是不可能的。
求个数就是用排列组合了。
给定字符串,判断任意交换顺序,能产生几个回文串。
先判定0,如果有超过一个字母出现的次数那么就是不可能的。
求个数就是用排列组合了。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define M 1009 typedef long long ll; char s[M]; int num[26]; const int mod = 1000000007; ll qpow(ll x,ll n,ll mod) { ll ans = 1; while(n) { if(n & 1) ans = ans * x % mod; x = x * x % mod; n >>= 1; } return ans; } ll C(ll a,ll b) { ll s1 = 1, s2 = 1; for(int i = b - a + 1;i <= b;i++) s1 = s1*i%mod; for(int i = 1;i <= a;i++) s2 = s2*i%mod; ll inv = qpow(s2,mod-2,mod); return s1*inv%mod; //return (s1%(s2*mod))/s2; } int main() { ios::sync_with_stdio(false); int T; cin >> T; while(T--) { cin >> s; memset(num,0,sizeof(num)); int len = strlen(s); for(int i = 0;i < len;i++) num[s[i] - 'a']++; int sum = 0; for(int i = 0;i < 26;i++) { if(num[i]&1) sum++; } if(sum > 1) { cout << 0 << endl; continue; } ll ans = 1; sum = len/2; //只看左半边 for(int i = 0;i < 26;i++) { if(!num[i]) continue; if(num[i] & 1) num[i]--; ans = ans*C(num[i]/2,sum)%mod; sum -= num[i]/2; //已经放过的位置要减掉 } cout << ans << endl; } return 0; }
相关文章推荐
- java权限设置文件-java.policy
- IDEA 中的简单单元测试配置
- 最简单是使用viewpager的方法
- mfc-串口控件的添加和使用
- Object-C 获取对象的属性和值
- 回溯法
- Android 布局属性 Android:layout_weight 总结
- Myeclipes8.0, 8.5 中安装SVN插件小结
- 请求码(requestCode)与结果码(resultCode)解析
- 请求码(requestCode)与结果码(resultCode)解析
- iptables端口转发配置[Ubuntu]
- DataGridView打印类
- HashSet 源码解读
- nginx配置websocket
- HDU 4745 Two Rabbits 区间dp
- [译]用NGINX最大化发挥PYTHON性能
- Opencv2相似图像检索
- linux期中总结
- [Java] 作业4答疑
- 让linux每天定时备份MySQL数据库并删除五天前的备份文件