• poj2409:Let it Bead(置换群 polya定理)


      题目大意:长度为n的项链,要染m种颜色,可以通过旋转或翻转到达的状态视为同一种,问有多少种染色方案。

      学了一波polya定理,发现很好理解啊,其实就是burnside定理的扩展。

      burnside定理告诉我们不同染色方案数是每种置换的不变元素个数除以置换总数,而polya定理就是在这个基础上用公式计算出置换的不变元素个数。而且polya定理非常好理解,我们要让元素不变,所以对于每个循环节我们要染一样的颜色,有m种颜色,c(pk)个循环节,于是每种置换的不变元素个数就是m^c(pk)。

      对于这道题,有两种操作。

      ①旋转。有n种置换,分别是1次旋转1个珠子,2个,3个...n个。对于1次旋转i个珠子,我们要求出循环节数可以先求出循环长度,一个位置置换x次之后回到原位,所以x=n*y/i,要使x尽量小且为整数那么n*y只能是lcm(n,i),于是循环长度为lcm(n,i)/i,那么循环节数为总长除以循环长度,n/(lcm(n,i)/i)=gcd(n,i)【n*i/gcd(n,i)=lcm(n,i)】。所以1次旋转i个珠子的循环节数为gcd(n,i)。

      ②翻转。对于奇偶性分类讨论。

      (1)n为奇数。对于每个点作为对称轴左右翻转,则共n个置换,循环节数(n+1)/2。

      (2)n为偶数。

      a.对于对称的两个点作为对称轴左右翻转。n/2个置换,循环节数(n+2)/2。

      b.对于两个点中间的空格作为对称轴左右反转,n/2个置换,循环节数n/2。

      则共n个置换。

      所以不论奇偶总置换数为2n,答案为sum/2n。

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    using namespace std;
    int n,m;
    int qp(int a,int b)
    {
        int t=1,y=a;
        while(b)
        {
            if(b&1)t*=y;
            y*=y;
            b>>=1;
        }
        return t;
    }
    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    int main()
    {
        while(~scanf("%d%d",&m,&n)&&(m||n))
        {
            int sum=0;
            for(int i=1;i<=n;i++)sum+=qp(m,gcd(n,i));
            if(n&1)for(int i=1;i<=n;i++)sum+=qp(m,(n+1)/2);
            else for(int i=1;i<=n/2;i++)sum+=qp(m,(n+2)/2)+qp(m,n/2);
            printf("%d
    ",sum/(2*n));
        }
    }
    View Code
  • 相关阅读:
    paip.数据库全文检索 attilax总结
    软件网站安全性的设计与检测与解决方案
    防止SQL注入解决方案
    paip.账务系统的安全性
    快速开发字段很多的MIS表
    paip.php调试不能显示局部变量内容w/ xdebug
    程序安全性之配置文件安全
    paip.VS2010未能加载类型
    paip.盘古汉字转拼音组件库使用总结
    paip.跟踪DISCUZ积分日志功能总结
  • 原文地址:https://www.cnblogs.com/Sakits/p/6985058.html
Copyright © 2020-2023  润新知