ACM: polay定理 数论题 poj 1286  …

本文介绍如何运用Polya定理解决手镯染色问题,具体包括理解置换群、循环节的概念,利用Burnside引理计算不同形式的手镯数量,并给出相应的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                                        Necklace of Beads

Description

Beads of red, blue or green colors are connected together into a circular necklace of n beads ( n < 24 ). If the repetitions that are produced by rotation around the center of the circular necklace or reflection to the axis of symmetry are all neglected, how many different forms of the necklace are there?

ACM: <wbr>polay定理 <wbr>数论题 <wbr>poj <wbr>1286 <wbr> <wbr>(神马置换!神马循环节!神马polay定理!)

Input

The input has several lines, and each line contains the input data n.
-1 denotes the end of the input file.

Output

The output should contain the output data: Number of different forms, in each line correspondent to the input data.

Sample Input

4

5

-1

Sample Output

21

39

题意: 在一个手镯上有n个地方着3种不同的颜色,问有多少种可能.(有些不同的方案经过旋转,翻转会是相同).

 

解题思路:

                1. 第一题polay定理题. 公式: L = (1/|G|) * (m^a1 + m^a2 + m^a3+...+ m^an);

                   G: 置换群的元素数量, m: 状态个数(着色的颜色数量). ai: 循环节.

                2. 引入一个Burnside引理:  等价类数目|L| = 所有不动点之和C(f)的平均值.  (花了点时间的定理,神奇!)

                  ∑C(f) = ∑|Zk| = ∑ |EL(1)|*|ZL(1)| = ∑|G| = |L| * |G|          (L(1) 是等价类L的任意元素)

                  |L| = 1/|G| * ∑C(f)

                   (1).G是1~n的置换群.

                   (2).k是1~n的的某个元素.

                   (3).Ek是把G中让k保持不变的置换集合.

                   (4).Zk是通过置换G能变换到的元素集合.

                 定理: 若G是一个置换群,对于1~n的任意元素k, 有|Ek| * |Zk| = |G|

                 

               3. 问题的置换及循环节数的计算方法:对于有n个位置的手镯,有n种旋转置换和n种翻转置换.
                                          对于旋转置换: c(fi) = gcd(n,i)  i为一次转过i颗宝石( i = 0 时 c=n;);
                                          对于翻转置换:

                                                                如果n为偶数:c(f) = n/2 的置换有n/2个; 
                                                                                       c(f) = n/2+1 的置换有n/2个;
                                                                 如果n为奇数:c(f) = n/2+1.

代码:

#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;

int n;

int gcd(int a,int b)
{
    if(b == 0)
        return a;
    else
        return gcd(b,a%b);
}

int polgy()
{
    double sum = 0;
    double t;
    
    for(int i = 1; i <= n; ++i)
        sum += pow(3,gcd(i,n));
        
    if(n % 2 == 0)
        sum += pow(3,n/2+1)*(n/2) + pow(3,n/2)*(n/2);
    else
        sum += pow(3,n/2+1)*n;
        
    return sum / 2 / n;
}

int main()
{
//    freopen("input.txt","r",stdin);
    while(scanf("%d",&n) != EOF && n != -1)
    {
        if(n == 0)
            printf("0\n");
        else
            printf("%d\n",polgy());
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值