poj 2409 Let it Bead Polya定理

题意:用c种颜色给长度为s的项链染色,一共有多少种方案


思路:网选后天就来了,这两天补了下Polya定理,刚好又在学习密码学,顺便补了群的一些东西。对于这种存在置换后存在一个等价类的计数问题,我们可以用Burnside引和Polya定理,Polya定理是由Burnside定理推导出来的,学习过程应该是群->置换群->Burnside引理->Polya定理,同时可以看见的是尽管Polya定理是由Burnside引理推导出来的,但也可以看作是两个看问题不同的角度而得出的结论,Burnside引理着眼于染色,如果颜色种类过多和被染色的图形过于复杂,那么Burnside引理将很难操作,而Polya定理则着眼于图形的结构,使问题的复杂性大大降低,数学真是处处充满哲理,不同角度看问题可能会产生非常大的差别


按照顺时针方向从0到n - 1进行编号,Polya定理是对结构进行置换,只考虑旋转的话,有n种结构,分别是旋转0, 1,  2, ... , n - 1,假定现在旋转了k次,

那么第i个钻石和第(i + k * t)属于同一个循环,那么如果求出一个最小的t使得(i + k * t ) % n == i,那么此时表明这个循环就有t个元素,上述式子可以推出i % n + k * t % n == i,可推出(k * t) % n == 0,此时t要取最小,必然t = n / gcd(k, n):t表示一个循环的阶,那么n / t就表示有多少个循环,从对称性上讲,也可看出是正确的。

当然还要考虑翻转的情况


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


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

typedef long long ll;

ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

ll mypow(ll x, ll n)
{
	ll res = 1;
	while(n)
	{
		if(n & 1) res *= x;
		x *= x;
		n >>= 1;
	}
	return res;
}

ll c, s;

ll polya()
{
	ll ans = 0;
	for(ll i = 1; i <= s; i++)
		ans += mypow(c, gcd(i, s)); 
	if(s & 1)
		ans += s * mypow(c, (s + 1) / 2);
	else
		ans += (s / 2) * (mypow(c, s / 2 + 1) + mypow(c, s / 2));
	return ans / 2 / s;
}

int main()
{
	while(scanf("%lld%lld", &c, &s), c)
	{
		ll ans = polya();
		printf("%lld\n", ans);
	}
	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值