@ruanxingzhi
2016-12-20T14:12:09.000000Z
字数 1280
阅读 1416
这是组合数学中著名的定理。用于解决“本质不同的染色方案”计数问题。
现在需要给的棋盘黑白染色。求本质不同的染色方案数。
如果某染色方案经过顺时针旋转后与别的染色方案相同,则称它们本质相同。
我们先暴力列出每种染色方案:
发现本质不同的染色方案数有种:C1,C2,C6,C10,C12,C16
。
bunside引理是polya定理的基础。
为了讨论方便,先给格子编号。
首先考虑“旋转”的本质——置换。旋转给出了一些置换方式,例如顺时针旋转,用置换的语言说就是“原来的位置是1
的现在摆在2
,原来位置是2
的现在摆在3
……”,表示为。类似地,我们搞出所有的置换:
接下来就是bunside引理
了:
对于每个置换,我们定义为在置换 下保持不变的方案数。
则有: 本质不同的方案数为的平均数。
即:
用上面的例子来验证一下:
置换 | 保持不变的方案 | |
---|---|---|
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 | 16 | |
1,16 | 2 | |
1,10,11,16 | 4 | |
1,16 | 2 |
则的平均数为:,发现确实是答案。
上面的bunside引理
很好用,然而它需要枚举每个方案,复杂度十分不好。
所以polya定理
出来拯救世界了。它提供了一种快速计算的方法:
考虑置换,我们一定能把它表示成循环的形式。例如上面的转可以表示为:。
令表示置换的循环节个数,表示有多少种颜色。则有:
我们还是使用之前的例子来验证。
角度 | 置换 | ||
---|---|---|---|
从上面的例子中我们发现,确实等于。现在我们的任务只是求出了。它显然可以求出:
int flag[10]={0},i,j,m=0;
for(i=1;i<=4;i++)
if(flag[i]==0)
{
j=i;
while(flag[j]==0)
flag[j]=1,j=f[j];
m++;
}
所以现在我们可以以的时间复杂度来求出整个问题的解。其中表示置换数量。
是不是很简单?