手链样式
小明有3颗红珊瑚,4颗白珊瑚,5颗黄玛瑙。
他想用它们串成一圈作为手链,送给女朋友。
现在小明想知道:如果考虑手链可以随意转动或翻转,一共可以有多少不同的组合样式呢?
请你提交该整数。不要填写任何多余的内容或说明性的文字。
1170
有重复计数的圆排列和环排列问题
可以随意转动和反转,意味着这个序列的圆排列和环排列看做是相同的组合方式
检查一个字符串序列是否在一种组合方式的圆排列和环排列中出现过,就把这种组合方式的2个同样字符串拼接在一起
如果在其中查找到该字符串,说明在其圆排列中出现过
然后将拼接后的字符串翻转之后再查找,说明在其环排列中出现过
进行全排列的一个代码模板:
do{
}while(next_permutation(start,end))
next_permutation(start,end)
函数的本意是查找一个序列的下一个全排列,如果有则返回1(并且将序列修改为下一个全排列),反之为0
reverse()函数将一个序列前后反转
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main(){
string s = "aaabbbbccccc";
vector<string> v1;
int ans = 0;
do{
int i = 0;
for(;i<v1.size();i++){
if(v1[i].find(s) != string::npos)
break;
}
if(i != v1.size())
continue; //如果s能在当前已找到的所有排列的圆排列和环排列中找到,说明这是一种已经出现过的组合方式
//对于已经找到的一种新的组合方式
string s2 = s + s;
v1.push_back(s2); //把检查圆排列的字符串放进去
reverse(s2.begin(),s2.end());
v1.push_back(s2); //把检查环排列的字符串放进去
ans++;
}while(next_permutation(s.begin(),s.end()));
cout << ans << endl;
return 0;
}