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

poj-2409 Let it Bead

时间:2015-07-22 16:12:46      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:poj   polya定理   

题意:

给出c种颜色和s个珠子;

将珠子染色后穿成一个环;

旋转和翻转相同的视为同构;

求方案数;


题解:

polya计数的裸题;

定义m为颜色数,c(Pi)为Pi这个置换的循环节个数;

那么根据定理,答案L为;

技术分享
然后只要求出各个置换的循环节就好了;

题中允许两种置换,先考虑旋转;

旋转有n种置换方式,分别是转0,转360/n,转2*360/n......转(n-1)*360/n;

每种的循环节数实际上是gcd,然后带入求和式;

然后考虑翻转,有奇偶的讨论;

奇数可以过每个珠子做对称轴,那么置换数就是n,循环节数都是n/2+1;

偶数可以过两个对角的珠子做对称轴,置换数是n/2,循环节数是n/2+1(其他的珠子除以2,加上轴上的两个);

也可以不过珠子,这样的置换数同样是n/2,循环节数是n/2了;

然后除个2*n就结束了;


代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110000
using namespace std;
typedef long long ll;
int gcd(int a,int b)
{
	int t=a%b;
	while(t)
	{
		a=b,b=t;
		t=a%b;
	}
	return b;
}
int pow(int x,int y)
{
	int ret=1;
	while(y)
	{
		if(y&1)
			ret*=x;
		x*=x;
		y>>=1;
	}
	return ret;
}
int main()
{
	int n,m,i,j,k;
	while(scanf("%d%d",&m,&n)&&(n||m))
	{
		for(i=1,k=0;i<=n;i++)
			k+=pow(m,gcd(n,i));
		if(n&1)
			k+=n*pow(m,n/2+1);
		else
			k+=n/2*pow(m,n/2)+n/2*pow(m,n/2+1);
		k/=2*n;
		printf("%d\n",k);
	}
	return 0;
}


poj-2409 Let it Bead

标签:poj   polya定理   

原文地址:http://blog.csdn.net/ww140142/article/details/47003643

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