符文杰Word文档下载推荐.docx
《符文杰Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《符文杰Word文档下载推荐.docx(11页珍藏版)》请在冰豆网上搜索。
eG,aG,a*e=e*a=a。
(d)逆元:
aG,bG,a*b=b*a=e,记b=a-1。
则称集合G在运算*之下是一个群,简称G是群。
一般a*b简写为ab。
置换:
n个元素1,2,…,n之间的一个置换
表示1被1到n中的某个数a1取代,2被1到n中的某个数a2取代,直到n被1到n中的某个数an取代,且a1,a2,…,an互不相同。
本例中有4个置换:
转0a1=
转90a2=
转180a3=
转270a4=
置换群:
置换群的元素是置换,运算是置换的连接。
例如:
可以验证置换群满足群的四个条件。
本题中置换群G={转0、转90、转180、转270}
我们再看一个公式:
│Ek│·
│Zk│=│G│k=1…n
该公式的一个很重要的研究对象是群的元素个数,有很大的用处。
Zk(K不动置换类):
设G是1…n的置换群。
若K是1…n中某个元素,G中使K保持不变的置换的全体,记以Zk,叫做G中使K保持不动的置换类,简称K不动置换类。
如本例中:
G是涂色方案1~16的置换群。
对于方案1,四个置换都使方案1保持不变,所以Z1={a1,a2,a3,a4};
对于方案3,只有置换a1使其不变,所以Z3={a1};
对于方案11,置换a1和a3使方案其保持不变,所以Z11={a1,a3}。
Ek(等价类):
若K是1…n中某个元素,K在G作用下的轨迹,记作Ek。
即K在G的作用下所能变化成的所有元素的集合。
方案1在四个置换作用下都是方案1,所以E1={1};
方案3,在a1下是3,在a2下变成6,在a3下变成5,在a4下变成4,所以E3={3,4,5,6};
方案11,在a1、a3下是11,在a2、a4下变成12,所以E11={11,12}。
本例中的数据,也完全符合这个定理。
│E1│·
│Z1│=14=4=│G│
│E3│·
│Z3│=41=4=│G│
│E11│·
│Z11│=22=4=│G│
限于篇幅,这里就不对这个定理进行证明。
接着就来研究每个元素在各个置换下不变的次数的总和。
见下表:
置换\Sij\元素j
aI
1
2
……
16
D(ai)
a1
a2
a3
a4
S1,1
S2,1
S3,1
S4,1
S1,2
S2,2
S3,2
S4,2
S1,16
S2,16
S3,16
S4,16
D(a1)
D(a2)
D(a3)
D(a4)
│Zj│
│Z1│
│Z2│
│Z16│
其中
D(aj)表示在置换aj下不变的元素的个数
如本题中:
涂色方案1在a1下没变动,S1,1=1;
方案3在a3变动了,S3,3=0;
在置换a1的变化下16种方案都没变动,D(a1)=16;
在置换a2下只有1、2这两种方案没变动,D(a2)=2。
一般情况下,我们也可以得出这样的结论:
我们对左式进行研究。
不妨设N={1,……,n}中共有L个等价类,N=E1+E2+……+EL,则当j和k属于同一等价类时,有│Zj│=│Zk│。
所以
这里的L就是我们要求的互异的组合状态的个数。
于是我们得出:
利用这个式子我们可以得到本题的解L=(16+2+4+2)/4=6与前面枚举得到的结果相吻合。
这个式子叫做Burnside引理。
但是,我们发现要计算D(aj)的值不是很容易,如果采用搜索的方法,总的时间规模为O(nsp)。
(n表示元素个数,s表示置换个数,p表示格子数,这里n的规模是很大的)下一步就是要找到一种简便的D(aj)的计算方法。
先介绍一个循环的概念:
循环:
记
称为n阶循环。
每个置换都可以写若干互不相交的循环的乘积,两个循环(a1a2…an)和(b1b2…bn)互不相交是指aibj,i,j=1,2,…,n。
这样的表示是唯一的。
置换的循环节数是上述表示中循环的个数。
例如(13)(25)(4)的循环节数为3。
有了这些基础,就可以做进一步的研究,我们换一个角度来考虑这个问题。
我们给2*2方阵的每个方块标号,如下图:
2
1
3
4
构造置换群G'
={g1,g2,g3,g4},|G'
|=4,令gi的循环节数为c(gi)(i=1,2,3,4)
在G'
的作用下,其中
g1表示转0°
即g1=
(1)
(2)(3)(4)c(g1)=4
g2表示转90°
即g2=(4321)c(g2)=1
g3表示转180°
即g3=(13)(24)c(g3)=2
g4表示转270°
即g4=(1234) c(g4)=1
我们可以发现,gi的同一个循环节中的对象涂以相同的颜色所得的图像数mc(gi)正好对应G中置换ai作用下不变的图象数,即
2c(g1)=24=16=D(a1)2c(g2)=21=2=D(a2)
2c(g3)=22=4=D(a3)2c(g4)=21=2=D(a4)
由此我们得出一个结论:
设G是p个对象的一个置换群,用m种颜色涂染p个对象,则不同染色方案为:
其中G={g1,…gs}c(gi)为置换gi的循环节数(i=1…s)
这就是所谓的Pó
lya定理。
我们发现利用Pó
lya定理的时间复杂度为O(sp)(这里s表示置换个数,p表示格子数),与前面得到的Burnside引理相比之下,又有了很大的改进,其优越性就十分明显了。
lya定理充分挖掘了研究对象的内在联系,总结了规律,省去了许多不必要的盲目搜索,把解决这类问题的时间规模降到了一个非常低的水平。
现在我们把问题改为:
nn的方阵,每个小格可涂m种颜色,求在旋转操作下本质不同的解的总数。
先看一个很容易想到的搜索的方法。
(见附录)
这样搜索的效率是极低的,它还有很大的改进的余地。
前面,我们采用的方法是先搜后判,这样的盲目性极高。
我们需要边搜边判,避免过多的不必要的枚举,我们更希望把判断条件完全融入到搜索的边界中去,消灭无效的枚举。
这个美好的希望是可以实现的。
我们可以在方阵中分出互不重叠的长为[(n+1)/2],宽为[n/2]的四个矩阵。
当n为偶数时,恰好分完;
当n为奇数时,剩下中心的一个格子,它在所有的旋转下都不动,所以它涂任何颜色都对其它格子没有影响。
令m种颜色为0~m-1,我们把矩阵中的每格的颜色所代表的数字顺次(左上角从左到右,从上到下;
右上角从上到下,从右到左;
……)排成m进制数,然后就可以表示为一个十进制数,其取值范围为0~m[n2/4]-1。
(因为[n/2]*[(n+1)/2]=[n2/4])这样,我们就把一个方阵简化为4个整数。
我们只要找到每一个等价类中左上角的数最大的那个方案(如果左上角相同,就顺时针方向顺次比较)这样,在枚举的时候其它三个数一定不大于左上角的数,效率应该是最高的。
进一步考虑,当左上角数为i时,(0iR-1)令R=m[n2/4]
可分为下列的4类:
其它三个整数均小于i,共i3个。
右上角为i,其它两个整数均小于i,共i2个。
右上角、右下角为i,左下角不大于i,共i+1个。
右下角为i,其它两个整数均小于i,且右上角的数不小于左下角的,共i(i+1)/2个。
因此,
当n为奇数时,还要乘一个m。
由此我们就巧妙地得到了一个公式。
但是,我们应该看到要想到这个公式需要很高的智能和付出不少的时间。
另一方面,这种方法只能对这道题有用而不能广泛地应用于一类试题,具有很大的不定性因素。
因此,如果能掌握一种适用面广的原理,就会对解这一类题有很大的帮助。
下面我们就采用Pó
我们可以分三步来解决这个问题。
1.确定置换群
在这里很明显只有4个置换:
转0、转90、转180、转270。
所以,置换群G={转0、转90、转180、转270}。
2.计算循环节个数
首先,给每个格子顺次编号(1~n2),再开一个二维数组记录置换后的状态。
最后通过搜索计算每个置换下的循环节个数,效率为一次方级。
3.代入公式
即利用Pó
lya定理得到最后结果。
【程序题解】
const
maxn=10;
var
a,b:
array[1..maxn,1..maxn]ofinteger;
{记录方阵的状态}
i,j,m,n:
integer;
{m颜色数;
n方阵大小}
l,l1:
longint;
procedurexz;
{将方阵旋转90}
i,j:
begin
fori:
=1tondo
forj:
a[j,n+1-i]:
=b[i,j];
b:
=a
end;
procedurexhj;
{计算当前状态的循环节个数}
i,j,i1,j1,k,p:
k:
=0;
{用来记录循环节个数,清零}
ifa[i,j]>
0then{搜索当前尚未访问过的格子}
begin
inc(k);
{循环节个数加1}
i1:
=(a[i,j]-1)divn;
j1:
=(a[i,j]-1)modn+1;
{得到这个循环的下一个格子}
a[i,j]:
{表示该格已访问}
whilea[i1,j1]>
0dobegin
p:
=a[i1,j1];
{暂存当前格的信息}
a[i1,j1]:
{置已访问标志}
=(p-1)divn+1;
=(p-1)modn+1{得到这个循环的下一个格子}
end{直到完整地访问过这个循环后退出}
end;
l1:
=1;
=1tokdol1:
=l1*m;
{计算m的k次方的值}
l:
=l+l1{进行累加}
writeln('
Inputm,n='
);
readln(m,n);
{输入数据}
=1tondoa[i,j]:
=(i-1)*n+j;
{对方阵的状态进行初始化}
=a;
xhj;
{计算转0状态下的循环节个数}
xz;
{转90}
{计算转90状态下的循环节个数}
{再转90}
{计算转180状态下的循环节个数}
{计算转270状态下的循环节个数}
=ldiv4;
writeln(l);
{输出结果}
readln
end.
在上面的程序中,我暂时回避了高精度计算,因为这和我讲的内容关系不大。
如果大家再仔细地考虑一下,就会发现这个题解还可以继续优化。
对n分情况讨论:
n为偶数:
在转0时,循环节为n2个,转180时,循环节为n2/2个,转90和转270时,循环节为n2/4个。
在转0时,循环节为n2个,转180时,循环节为(n2+1)/2个,转90和转270时,循环节为(n2+3)/4个。
把这些综合一下就得到:
在转0时,循环节为n2个,转180时,循环节为[(n2+1)/2]个,转90和转270时,循环节为[(n2+3)/4]个。
(其中,方括号表示取整)于是就得到:
这和前面得到的结果完全吻合。
经过上述一番分析,使得一道看似很棘手的问题得以巧妙的解决,剩下的只要做一点高精度计算即可。
通过这几个例子,大家一定对Pó
lya原理有了八九成的了解,通过和搜索方法的对比,它的优越性就一目了然了。
它不仅极大地提高了程序的时间效率,甚至在编程难度上也有减无增。
所以,我们在智能和经验不断增长的同时,也不能忽视了原理性的知识。
智能和经验固然重要,但是掌握了原理就更加踏实。
因此,我们在解题之余,也要不忘对原理性知识的学习,不停给自己充电,使自己的水平有更大的飞跃。
附录(搜索方法的程序)
type
sqtype=array[1..maxn,1..maxn]ofbyte;
n,total,m:
sq:
sqtype;
functionbig:
boolean;
(检验当前方案是否为同一等价类中最大的)
units:
array[2..4]ofsqtype;
(记录三种旋转后的状态)
i,j,k:
=1tondobegin
units[2,j,n+1-i]:
=sq[i,j];
units[3,n+1-i,n+1-j]:
units[4,n+1-j,i]:
=sq[i,j]
big:
=false;
fork:
=2to4do(进行比较)
j:
while(j<
=n)and(sq[i,j]=units[k,i,j])doinc(j);
ifj<
=nthen
ifsq[i,j]<
units[k,i,j]
thenexit
elsebreak
=true
proceduremake(x,y:
byte);
(枚举每个格子中涂的颜色)
vari:
ifx>
nthenbegin
ifbigtheninc(total);
exit
=1tomdobegin
sq[x,y]:
=i;
ify=nthenmake(x+1,1)elsemake(x,y+1)
end
readln(m,n);
total:
make(1,1);
writeln(total);
readln
end.