zoukankan      html  css  js  c++  java
  • poj 1286 Necklace of Beads 题解

    传送门


    【题意】

    给定 (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('};')
    
  • 相关阅读:
    是否可以从一个静态(static)方法内部发出对非静态 (non-static)方法的调用?
    是否可以继承 String 类?
    如何实现字符串的反转及替换?
    String s = new String(“xyz”);创建了几个字符串对象?
    Serial 与 Parallel GC 之间的不同之处?
    SVG是什么?
    阐述静态变量和实例变量的区别?
    Java 中 ++ 操作符是线程安全的吗?
    什么是 REST / RESTful 以及它的用途是什么?
    WebSQL是HTML 5规范的一部分吗?
  • 原文地址:https://www.cnblogs.com/JustinRochester/p/14993830.html
Copyright © 2011-2022 走看看