polya定理

设有(n)个对象,(G)是这(n)个对象上的置换群,用(m)种颜色涂染着(n)个对象,每个对象涂一种颜色,问有多少种染色方案

[M = frac{1}{|G|}sum_{i = 1}^{|G|}m^{c(sigma_i)} ]

(G = {sigma_1,sigma_2,dots,sigma_k})(c(sigma_i))为置换(sigma_i)的循环节数

集合(G)(G)上的二元运算,满足下列条件称为群:

  • 封闭性
  • 结合律
  • 有单位元
  • 有逆元

置换群

([1,n])到自身(1-1)映射称为(n)阶置换。([1,n])目标集上的置换表示为

置换

[sigma(1) = a_1,sigma(2) = a_2dots sigma(n) = a_n ]

(a_n)([1,n])中元的一个排列

举个例子,这是个(n = 5)的5元置换,(sigma(1) = 3,sigma(3) = 1),构成循环,(sigma(4) = 4),4的置换是本身,也是一个循环,所以也可以写成(sigma = (1,3)(4)(2,5)),一般一阶轮换(4)不写,(sigma = (1,3)(2.5))

img

正三角形

![114E8C20-99B6-41DB-988E-F314FA43C464](/Users/i/Library/Containers/com.tencent.qq/Data/Library/Application Support/QQ/Users/2287697454/QQ/Temp.db/114E8C20-99B6-41DB-988E-F314FA43C464.png)

旋转0°:(p1 = egin{array}{l} left(egin{array}{l} 1&2&3\ 1&2&3 end{array} ight) end{array})

旋转120°:(p2 = egin{array}{l} left(egin{array}{l} 1&2&3\ 2&3&1 end{array} ight) end{array})

旋转240°:(p3 = egin{array}{l} left(egin{array}{l} 1&2&3\ 3&1&2 end{array} ight) end{array})

对称:(p4 = egin{array}{l} left(egin{array}{l} 1&2&3\ 1&3&2 end{array} ight) end{array})(p5 = egin{array}{l} left(egin{array}{l} 1&2&3\ 3&2&1 end{array} ight) end{array})(p6 = egin{array}{l} left(egin{array}{l} 1&2&3\ 2&1&3 end{array} ight) end{array})

正四边形

旋转0°:(p1 = egin{array}{l} left(egin{array}{l} 1&2&3 &4\ 1&2&3&4 end{array} ight) end{array})

旋转90°:(p2 = egin{array}{l} left(egin{array}{l} 1&2&3&4\ 4&1&2&3 end{array} ight) end{array})

旋转180°:(p3 = egin{array}{l} left(egin{array}{l} 1&2&3&4\ 3&4&1&2 end{array} ight) end{array})

旋转270°:(p4 = egin{array}{l} left(egin{array}{l} 1&2&3&4\ 2&3&4&1 end{array} ight) end{array})

对称:(p5 = egin{array}{l} left(egin{array}{l} 1&2&3&4\ 1&4&3&2 end{array} ight) end{array})(p6 = egin{array}{l} left(egin{array}{l} 1&2&3&4\ 3&2&1&4 end{array} ight) end{array})(p7 = egin{array}{l} left(egin{array}{l} 1&2&3&4\ 2&1&4&3 end{array} ight) end{array})(p8 = egin{array}{l} left(egin{array}{l} 1&2&3&4\ 4&3&2&1 end{array} ight) end{array})

image-20200607214356899

旋转0°:((1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(13)(14)(15)(16))

旋转90°:((1)(2 3 4 5)(6 7)(8 9 10 11)(12 13 14 15)(16))

旋转180°:((1)(2 4)(3 5)(6)(7)(8 10)(9 11)(12 14)(13 15)(16))

旋转270°:((1)(2 3 4 5)(6 7)(8 9 10 11)(12 13 14 15)(16))

(l = frac{16 + 2 + 4 + 2}{4} =)

Bunruside引理

等价类

k阶不动置换类

(G)(1,2,dots ,n)的置换群,(k)(1dots n)中的某个元素,(G)中使(k)保持不变的置换的全体,极为(Z_k)

Polya置换

(N = {1,2,dots, n})是被着色物体的集合,(G = {sigma_1,sigma_2,dots,sigma_g})(N)上的置换群,用(m)种颜色对(N)中的元素进行着色,则在(G)的作用下不同的着色方案数是

[M = frac{1}{|G|}sum_{i = 1}^{|G|}m^{c(sigma_i)} ]

其中(G = {sigma_1,sigma_2,dots,sigma_k})(c(sigma_i))为置换(sigma_i)的循环节数,即轮换个数,(|G|)表示置换种数

关键在于找到每个置换的循环节即可

对于这个置换

img

循环节是(1,3)(2,5)(4),所以循环节长度是3

利用polya定理

  1. 写出置换群
  2. 求出每个置换的轮换个数
  3. 带入公式求

写出有置换群

[egin{array}{l} left(egin{array}{l} 123456 \ 123456 end{array} ight)left(egin{array}{l} 123456 \ 612345 end{array} ight)left(egin{array}{l} 123456 \ 561234 end{array} ight) \ left(egin{array}{l} 123456 \ 456123 end{array} ight)left(egin{array}{l} 123456 \ 345612 end{array} ight)left(egin{array}{l} 123456 \ 234561 end{array} ight) end{array} ]

求出每个置换的轮换个数

(c_1 = (1)(2)(3)(4)(5)(6)=6, c_2 = (1,2,3,4,5,6) = 1,c_3 = (1,3,5)(2,4,6) = 2,\ c_4 = (1,4)(2,5)(3,6) = 3,c_5 = (1,3,5)(2,4,6) = 2,c_6 = (1,2,3,4,5) = 1)

带入公式,用2种颜色去染色

(M= frac{2^6+2^1+2^2+2^3+2^2+2^1}{6} = 14)

常见置换的轮换个数

旋转

n个点顺时针(或逆时针)旋转i个位置的置换,轮换个数是(gcd(n,i))

假设旋转i个单位,使得与原来重合,设执行k次,那么一定满足(i * k mod n == 0),那么解得最小(k = frac{lcm(i, n)}{i} = frac{n}{gcd(n, i)}),所以(frac{n}{k} = gcd(n,i))

翻转

n为偶数且对称轴不过顶点,轮换个数为(frac{n}{2})

n为偶数且对称轴过顶点,轮换个数为(frac{n}{2} + 1)

n为奇数,轮换个数为(frac{n + 1}{2})

模板

对于翻转,如果n为奇数,找个对称轴经过点,一共有n条对称轴,每条对称轴上有一个点,对称轴上的珠子构成了一个循环,其他(n-1)个珠子分别与对称轴对此构造成(frac{n - 1}{2})个循环,所以循环节个数是(frac{n - 1}{2} + 1 = frac{n + 1}{2})

如果n是偶数,对称轴上有两个点,一个有(frac{n}{2})条,对称轴上的两个点构成两个循环,其他(n - 2)个点分别以对称轴对此构成(frac{n - 2}{2})个循环。还有一种情况,对此轴穿过两个点之间,这时其他点两两对称,构成(frac{n}{2})个对称

对称有n个置换,旋转有n个置换,总共2n个置换

时间复杂度(O(nlogn))

#include <iostream>
#include <cstdio>
#define ll long long
int gcd(int a, int b){
    return b == 0 ? a : gcd(b, a % b);
}
ll pow(ll a, ll b){
    ll ans = 1;
    while(b){
        if(b & 1) ans = ans * a;
        a = a * a;
        b >>= 1;
    }
    return ans;
}
int main(){
    int n, m;
    while(~scanf("%d%d", &m, &n)){
        if(n == 0 && m == 0)break;
        ll ans = 0;
        for(int i = 1; i <= n; i++){
            ans += pow(m, gcd(i, n));
        }
        if(n & 1){
            ans += pow(m, n / 2 + 1) * n;
        }else{
            ans += pow(m, n / 2 + 1) * (n / 2);
            ans += pow(m, n / 2) * (n / 2);
        }
        printf("%lld
", ans / (2 * n));
    }
    return 0;
}

在旋转部分进行优化,(sum_{i = 1}^n n^{gcd(i,n)})

(sum_{d|n}n^d imessum_{k = 1}^{frac{n}{d}}[gcd(k,frac{n}{d}) == 1])

(sum_{d|n}n^dvarphi(frac{n}{d}))

时间复杂度(O(n^{frac{3}{4}}))

#include <iostream>
#include <cstdio>
#include <cmath>
#define ll long long
using namespace std ;
const int mod = 1e9 + 7 ; 
ll pow(ll a, ll b, ll p){
    ll ans = 1; a %= p;
    while(b){
        if(b & 1) ans = ans * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return ans;
}
ll phi(ll n) {
    ll ans = n; 
    for(int i = 2; i * i <= n; ++ i ) {
        if(n % i == 0){
            ans -= ans / i;
            while(n % i == 0) n /= i;
        }
    }
    if(n > 1) ans -= ans / n ;
    return ans ; 
}
int main(){
    int T, n, cnt;
    scanf("%d", &T); 
    while( T-- ) {
        scanf("%d", &n);
        ll ans = 0; 
        for(int i = 1; i * i <= n; i++) {
            if(n % i) continue;
            ll p1 = phi(i), f1 = pow(n, n / i, mod); 
            f1 = f1 * p1 % mod; ans = (ans + f1) % mod;
            if(i * i != n) {
                ll p2 = phi(n / i), f2 = pow(n, i, mod) ;
                f2 = f2 * p2 % mod; ans = (ans + f2) % mod;
            }
        }
        printf("%lld
", ans * pow(n, mod - 2, mod) % mod); 
    }
    return 0 ;
}
原文地址:https://www.cnblogs.com/Emcikem/p/13282509.html