1 条题解
-
0
解题思路
本题旨在求解由红、蓝、绿三色珠子组成的(n)颗珠子圆形项链,在忽略旋转和翻转重复情况下的不同形式数量。
- 计算初始状态数量:
power
函数用于计算(3)的(e)次幂。在不考虑旋转和翻转重复时,每颗珠子有(3)种颜色选择,(n)颗珠子的项链组合数为(3^n) ,在transf
函数中通过power(n)
得到此值并赋给add
。 - 考虑旋转对称情况:
通过枚举旋转间隔(d)((1)到(n - 1) )来处理旋转对称。对于每个(d),利用
while
循环标记访问过的珠子(借助visit
数组 ),计算在该旋转间隔下的循环节数量res
。每个循环节内珠子颜色组合数为(3^res) ,将其累加到add
中。这是因为旋转对称会使一些组合重复,需将这些重复组合按不同旋转情况统计并累加。 - 考虑翻转对称情况:
根据(n)的奇偶性分别处理翻转对称。
- 当(n)为奇数时,对称轴过一颗珠子和圆心,有(n)条对称轴。对于每条对称轴,对称轴两侧珠子对称,此时对称轴一侧珠子组合数为(3^{\frac{n + 1}{2}}) ,所以这部分组合数为(n\times3^{\frac{n + 1}{2}}) ,累加到
add
中,同时mapnum
加上(n) 。 - 当(n)为偶数时,有两种对称轴:一种过相对两颗珠子的中点和圆心,共(\frac{n}{2})条,每条对称轴对应一侧珠子组合数为(3^{\frac{n}{2}+1}) ;另一种过相对两颗珠子和圆心,共(\frac{n}{2})条,每条对称轴对应一侧珠子组合数为(3^{\frac{n + 1}{2}}) 。将这两部分组合数分别累加,同时
mapnum
加上(n) 。
- 当(n)为奇数时,对称轴过一颗珠子和圆心,有(n)条对称轴。对于每条对称轴,对称轴两侧珠子对称,此时对称轴一侧珠子组合数为(3^{\frac{n + 1}{2}}) ,所以这部分组合数为(n\times3^{\frac{n + 1}{2}}) ,累加到
- 计算最终结果:
将考虑旋转和翻转对称后的总组合数
add
除以总的对称情况数mapnum
,得到不同形式项链的数量并返回。在main
函数中循环读取输入的(n),调用transf
函数输出结果。
#include<iostream> using namespace std; #include <cstring> int n; bool visit[100]; long long power(int e){ long long res = 3; for(int i = 1; i < e; i++) res *= 3; return res; } long long transf(){ if(n==0) return 0; long long add = power(n),mapnum = n; for(int d = 1; d < n; d++){ memset(visit,0,sizeof(visit)); int res = 0, cnt = 0; while(cnt<n){ int st = 0; while(visit[st]) st++; while(visit[st]==0) visit[st] = 1, cnt++, st = (st+d)%n; res++; } add += power(res); } //cout << add << endl; if(n%2){ int t = power((n+1)/2); add += n*t; mapnum += n; } else{ int t = power((n+1)/2); add += n/2*t+n/2*power(n/2+1); mapnum += n; } //cout << add << " " << mapnum << endl; //add += power((n+1)/2); return add/mapnum; } int main(){ while(cin>>n&&n!=-1){ cout << transf() << endl; } }
- 计算初始状态数量:
- 1
信息
- ID
- 287
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 6
- 已通过
- 1
- 上传者