码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 2409 Let it Bead [置换群 Polya]

时间:2017-02-28 11:31:36      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:lcm   nbsp   定义   i++   print   stream   gcd   let   stdin   

传送门

题意:$m$种颜色$n$颗珠子,定义旋转和翻转两种置换,求不等价着色数


暴力求每个置换的循环节也许会$T?$

我们可以发现一些规律:

翻转:

$n$为奇数时每个置换有$1+\frac{n-1}{2}$个循环

$n$为偶数时穿过点的对称有$\frac{n}{2}$个循环,穿过边的有$\frac{n}{2}+1$个循环

旋转:

旋转$i$次的置换的循环个数为$gcd(n,i)$

可以这样想,从一个点开始每次走$i$步最后走到原位的最少步数$a$就是一个循环的长度

$ ai \equiv \pmod n$

$ i \mid ai,n \mid ai \rightarrow a=\frac{lcm(i,n)}{i}$

辣么$\frac{n}{a}=gcd(n,i)$就是循环个数啦

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1005;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1; c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0; c=getchar();}
    return x*f;
}
int m,n;
inline int Pow(int a,int b){
    int re=1;
    for(;b;b>>=1,a*=a)
        if(b&1) re*=a;
    return re;
}
inline int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int main(){
    freopen("in","r",stdin);
    while(true){
        m=read();n=read();
        if(m==0&&n==0) break;
        int ans=0;
        for(int i=0;i<n;i++) ans+=Pow(m,gcd(n,i));
        if(n&1) ans+=n*Pow(m,(n+1)>>1);
        else ans+=(n>>1)*Pow(m,n>>1)+(n>>1)*Pow(m,(n>>1)+1);
        ans/=n<<1;
        printf("%d\n",ans);
    }
}

 

POJ 2409 Let it Bead [置换群 Polya]

标签:lcm   nbsp   定义   i++   print   stream   gcd   let   stdin   

原文地址:http://www.cnblogs.com/candy99/p/6478051.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!