zoukankan      html  css  js  c++  java
  • POJ-2409 Let it Bead 【置换群-Polya定理】

    题目链接:http://poj.org/problem?id=2409

    Time Limit: 1000MS   Memory Limit: 65536K

    Description

    "Let it Bead" company is located upstairs at 700 Cannery Row in Monterey, CA. As you can deduce from the company name, their business is beads. Their PR department found out that customers are interested in buying colored bracelets. However, over 90 percent of the target audience insists that the bracelets be unique. (Just imagine what happened if two women showed up at the same party wearing identical bracelets!) It's a good thing that bracelets can have different lengths and need not be made of beads of one color. Help the boss estimating maximum profit by calculating how many different bracelets can be produced. 

    A bracelet is a ring-like sequence of s beads each of which can have one of c distinct colors. The ring is closed, i.e. has no beginning or end, and has no direction. Assume an unlimited supply of beads of each color. For different values of s and c, calculate the number of different bracelets that can be made.

    Input

    Every line of the input file defines a test case and contains two integers: the number of available colors c followed by the length of the bracelets s. Input is terminated by c=s=0. Otherwise, both are positive, and, due to technical difficulties in the bracelet-fabrication-machine, cs<=32, i.e. their product does not exceed 32.

    Output

    For each test case output on a single line the number of unique bracelets. The figure below shows the 8 different bracelets that can be made with 2 colors and 5 beads.

    Sample Input

    1 1
    2 1
    2 2
    5 1
    2 5
    2 6
    6 2
    0 0
    

    Sample Output

    1
    2
    3
    5
    8
    13
    21



    题目大意:给你c中颜色,s长度的项链,问有多少种本质不同的染色方案(可通过旋转,翻转得到的为同一种)。
    很显然这题要用到置换群的相关知识,而很显然这题如果一个一个找不动点的话很麻烦,我们直接找循环节数就好了,然后用Polya定理一波带走。。

    首先对于旋转,很明显其置换群的元素|G|=n(有n种置换)分别为步长为1到n的置换,举个例子,对于项链长度为4的时候:
    1 2
    3 4
    旋转步长为1,那么循环节数为1:(1,2,4,3)
    步长为2,循环节数为2:(1,4)(2,3)
    步长为3,循环节数为1:(1,3,4,2)
    步长为4,循环节数为4:(1)(2)(3)(4)

    我们可以知道步长为i时循环节长度为LCM(n,i)/i,那么其循环节节数为n/(LCM(n,i)/i),即gcd(n,i)
    那么对于步长为i的一种置换,其方案数为c^gcd(n,i)

    接下来就是翻转了,翻转分奇数偶数:
    当n为奇数的时候:

    选择1个顶点,划开两边,则有n个顶点,即n种置换,每种置换有n/2+1个循环节,如上图:设1为顶点,即循环节为:(1)(2,3)

    当n为偶数的时候,又分为2种情况:

    对于第一种情况没有不动点,那么循环节数为n/2,有n/2种翻转(即沿(1,2)翻转,沿(1,3)翻转...)
    对于第二种情况又两个不动点,那么循环节数为(n-2)/2+2=(n+2)/2,也有n/2种翻转。

    那么根据Polya定理就可以愉快地得出答案了。
    以下是AC代码:
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    int qick(int a,int b)
    {
        int ans=1;
        while (b){
            if (b&1) ans=ans*a;
            a*=a;
            b>>=1;
        }
        return ans;
    }
    
    int gcd(int a,int b)
    {
        return b==0?a:gcd(b,a%b);
    }
    
    int main()
    {
        int c,n;
        while (scanf ("%d%d",&c,&n)){
            if (c==0 && n==0) break;
            int ans=0;
            for (int i=1; i<=n; i++){
                ans+=qick(c,gcd(n,i));
            }
            if (n&1) ans+=qick(c,(n+1)/2)*n;
            else ans+=qick(c,n/2)*n/2+qick(c,(n+2)/2)*n/2;
            printf ("%d
    ",ans/(n*2));
        }
        return 0;
    }


    路漫漫兮
  • 相关阅读:
    redis学习
    win2008下c#调用directshow问题
    vs2005升级到vs2010相关问题
    spark-shell 启动失败,显示端口问题
    监控spark-sql 等脚本
    spark 相关配置 shuffle 相关配置选项
    spark on Yarn 语句
    使用hive thriftserver 连接spark sql
    HBase 报错系列之region is not online
    HBase 表迁移中对丢失的表检查使用的语句
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/12186739.html
Copyright © 2011-2022 走看看