题意
链接:https://ac.nowcoder.com/acm/contest/9854/D
光、对立和小红三个人在玩捉蛇游戏。已知蛇有三种:红蛇、蓝蛇和绿蛇。蛇可以咬住自己的尾巴,形成衔尾蛇。每条蛇可以咬住自己的尾巴,也可以咬住别的蛇的尾巴。一共有 (a) 条红蛇,(b) 条蓝蛇,(c) 条绿蛇。她们想知道一共可以形成多少种不同的衔尾蛇的环?
注:蛇可以不用全部用完。
(1≤a+b+c≤12)
分析
数据范围很小,明显可以直接枚举每种颜色的蛇的数量,将每种情况累加起来。计算的时候按可重集合和圆圈排列直接用公式算,但是二者并不可以直接一起使用,所以最后还是要暴力去判断环的重复情况。利用 ( ext{next_permutation()}) 可以直接生成各自排列组合的情况,利用 ( ext{rotate()}) 可以将一个排列对应的环的所有情况求出,利用 ( ext{set}) 去一下重即可。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int solve(int x,int y,int z)
{
string s=string(x,'a')+string(y,'b')+string(z,'c');
set<string>st;
do
{
string t1=s,t2=s;
int n=x+y+z;
for(int i=1;i<=n;i++)//圆圈枚举
{
rotate(t2.begin(),t2.begin()+1,t2.end());//中间的参数为下一个排列对应的开始位置
t1=min(t1,t2);
}
st.insert(t1);
}
while(next_permutation(s.begin(),s.end()));
return st.size();
}
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
ll ans=0;
for(int i=0;i<=a;i++)
{
for(int j=0;j<=b;j++)
{
for(int k=0;k<=c;k++)
{
if(i+j+k==0) continue;
ans+=solve(i,j,k);
}
}
}
printf("%lld
",ans);
return 0;
}