【题意】
给定 (n) 个空位待填的圆环,每个空位可以填入红、蓝、绿任一颜色的珠子。问不同构的方案数为多少?
题目认为旋转、沿坐标轴翻转后相同的两个方案是同构的。
(n<24)
【分析】
比较裸的 Polya 定理
旋转和翻转,以及这两个变换的运算构成一个群 (G) 。
而原本的翻转只能沿坐标轴翻转,但我们考虑先将圆环旋转 (- heta) 度的变换 (rot_{- heta}),再沿 (x) 轴翻转 (sym_0) ,最后再旋转 ( heta) 度 (rot_{ heta}) ,则等价于圆环沿 ( heta) 的这条极径进行了翻转 (sym_{ heta})。即 (sym_{ heta}=rot_{ heta}circ sym_{0}circ sym_{- heta}) 。
由于 (rot_{ heta}, sym_{0}, rot_{- heta}in G), 根据运算的封闭性,(sym_{ heta}in G) 。即群内包括了任意角度的旋转,和任意角度的翻转。
现考虑到旋转角度只有 (kcdot {2piover n}, kin{0, 1, 2, cdots, n-1}) 时才有意义,翻转角度只有 (kcdot {piover n}, kin{0, 1, 2, cdots, n-1}) 时才有意义
当旋转角度为 (kcdot {2piover n}) 时,构成置换 (left( egin{matrix} 1&2&3&cdots &n-k&n-k+1&cdots &n \\ k+1&k+2&k+3&cdots&n&1&cdots &k end{matrix} ight)),可拆解成 (gcd(k, n)) 个不可拆解的置换
当 (n) 为奇数时,翻转角度 (kcdot {piover n}) 使得除了直线上一点,其余每个点与关于直线的对称点构成一个置换,故可拆解成 (lceil{nover 2} ceil={n+1over 2}) 个不可拆解的置换
当 (n) 为偶数时,若 (k) 为奇数,则翻转角度 (kcdot {piover n}) 使得每个点与关于直线的对称点构成一个置换,可分解为 ({nover 2}) 个不可拆解的置换
当 (n) 为偶数时,若 (k) 为偶数,则翻转角度 (kcdot {piover n}) 使得除线上的两个点,每个点与关于直线的对称点构成一个置换,可分解为 (({nover 2}+1)) 个不可拆解的置换
故根据 Polya 定理:
当 (n) 为奇数时,方案数为 (displaystyle {1over 2n}(sum_{i=0}^{n-1} 3^{gcd(i, n)} + sum_{i=0}^{n-1} 3^{n+1over 2})={1over 2n}(sum_{i=0}^{n-1} 3^{gcd(i, n)} + ncdot 3^{n+1over 2}))
当 (n) 为偶数时,方案数为 (displaystyle {1over 2n}(sum_{i=0}^{n-1} 3^{gcd(i, n)} + sum_{i=0}^{n-1}3^{nover 2}[2 mid n]+sum_{i=0}^{n-1}3^{{nover 2}+1}[2mid n])={1over 2n}(sum_{i=0}^{n-1} 3^{gcd(i, n)} + 2ncdot 3^{nover 2}))
到这一步已经可以出答案了,不过本人顺着莫比乌斯反演推了推:
(displaystyle sum_{i=0}^{n-1} 3^{gcd(i, n)}=sum_{i=1}^n 3^{gcd(i, n)}=sum_{dmid n}3^dsum_{i=1}^n[gcd(i, n)=d]=sum_{dmid n}3^doldsymbol varphi({nover d}))
【代码】
本来是想 Python 直接冲的,猛地发现 POJ 不能交 Python,这里就直接敲了个表,然后 C++ 交上去
phi = [0, 1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8, 12, 10, 22, 8, 20, 12, 18, 12, 28, 8, 30]
pow3 = [1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467, 3486784401, 10460353203, 31381059609, 94143178827, 282429536481, 847288609443, 2541865828329, 7625597484987, 22876792454961, 68630377364883, 205891132094649, 617673396283947]
ans = [0]
for i in range(1, 32) :
tmp = 0
for d in range(1, i+1) :
if i%d == 0 :
tmp += 3**d*phi[i//d]
if i&1 :
tmp += i*3**((i+1)//2)
else :
tmp += i*2*3**(i//2)
tmp //= 2*i
ans.append(tmp)
print('ans[]={', end='0')
for i in range(1, 32) :
print(', %d'%ans[i], end='')
print('};')