群论什么的,略玄学…就算你看懂了…也不一定做得出题…
一开始看懂了一点…然而做的第一道题就让这只蒟蒻窒息了…所以写个笔记,也算留作以后复习使用,有错请指出谢了。
给定一个集合G和一个运算@,一个群(G,@)需要满足:
1.封闭性: ∀ a , b ∈ G , ∃ c ∈ G , a @ b = c \forall a,b \in G, \exists c \in G, a@b=c ∀a,b∈G,∃c∈G,a@b=c
2.结合律: ∀ a , b , c ∈ G , ( a @ b ) @ c = a @ ( b @ c ) \forall a,b,c \in G,(a@b)@c=a@(b@c) ∀a,b,c∈G,(a@b)@c=a@(b@c)
3.单位元: ∃ e ∈ G , ∀ a ∈ G , a @ e = e @ a = a \exists e \in G,\forall a \in G,a@e=e@a=a ∃e∈G,∀a∈G,a@e=e@a=a
4.逆元: ∀ a ∈ G , ∃ b ∈ G , a @ b = b @ a = e \forall a \in G, \exists b \in G, a@b=b@a=e ∀a∈G,∃b∈G,a@b=b@a=e,记 b = a − 1 b=a^{-1} b=a−1
以上摘自《信息学奥赛之数学一本通》
置换 ( 1 2 . . . n a 1 a 2 . . . a n ) \begin{pmatrix} 1 & 2 & ... & n \\ a_1& a_ 2 &...&a_n\end{pmatrix} (1a12a2......nan)的含义为原来数列为 ( 1 , 2 , . . . n ) (1,2,...n) (1,2,...n),用 a 1 a_1 a1代替1,用 a 2 a_2 a2代替2,用 a n a_n an代替n。其中, a 1 , a 2 . . . ∈ { 1 , 2 , . . . } a_1,a_2... \in \{ 1,2,...\} a1,a2...∈{1,2,...}且互不相同。
举个栗子QWQ,有三个同学A,B,C坐成一排,那么置换 ( 1 2 3 2 3 1 ) \begin{pmatrix} 1&2 &3\\2 &3 &1\end{pmatrix} (122331)就代表一次更换座位的过程。座位被换成了A,B,C
而置换群中的元素是置换,@运算则是置换之间的连接(如下)。
( 1 2 3 2 3 1 ) ( 2 3 1 3 2 1 ) = ( 1 2 3 3 2 1 ) \begin{pmatrix} 1&2 &3\\2 &3 &1\end{pmatrix}\begin{pmatrix} 2&3 &1\\3 &2 &1\end{pmatrix}=\begin{pmatrix} 1&2 &3\\3 &2 &1\end{pmatrix} (122331)(233211)=(132231)
检验一下发现,置换群满足群的定义。
问题:神明boshi(在mc里)创造天地,也创造众生。现在他要用m种颜色给n只绵羊染色,并且给出s个置换,用于置换绵羊。凡是通过这些置换可以变得一样的染色方案算作同一种,求boshi有多少种不同的染色方案。
对于一个置换 g g g,若存在一种染色方案 s s s,使得 s s s在经过该置换后不变,则称 s s s为 g g g的一个不动点。
设置换 g i g_i gi的不动点数目为 D ( g i ) D(g_i) D(gi), L L L表示本质不同的方案数, G G G是置换群中的集合,则有:
L = 1 ∣ G ∣ ∑ j = 1 s D ( g j ) L=\frac{1}{|G|}\sum_{j=1}^sD(g_j) L=∣G∣1j=1∑sD(gj)
即本质不同的方案数为置换的不动点数目的平均值。
注意有时一个置换做多次后会变成不同置换,要看题目怎么说。
现在我们定义循环 ( a 1 a 2 . . . a n ) = ( a 1 a 2 . . . a n a 2 a 3 . . . a 1 ) (a_1 a_2 ... a_n)=\begin{pmatrix} a_1&a_2 &... &a_n\\a_2 &a_3 &... &a_1\end{pmatrix} (a1a2...an)=(a1a2a2a3......ana1)
那么每一个置换就可以表示为执行若干循环的结果,例如: ( 1 2 3 3 2 1 ) = ( 13 ) ( 2 ) \begin{pmatrix} 1&2 &3\\3 &2 &1\end{pmatrix}=(13)(2) (132231)=(13)(2)(即交换1和3,2不变)
以上的表示法中,括号数=循环节数,记置换 g i g_i gi的循环节数为 c ( g i ) c(g_i) c(gi)。
Polya定理为(字母含义和Burnside引理中相同):
L = 1 ∣ G ∣ ∑ j = 1 s m c ( g j ) L=\frac{1}{|G|}\sum_{j=1}^s m^{c(g_j)} L=∣G∣1j=1∑smc(gj)
其实也就是同一个循环节染成同一种颜色,就是在置换下没有变化的方案啦,所以 D ( g i ) = m c ( g i ) D(g_i)=m^{c(g_i)} D(gi)=mc(gi)。
题目大意:用n种颜色染一个有n颗珠子的环形项链,可以通过旋转得到的相同方案视作相同,问有多少种不同的方案。
题目分析:
所有的置换很容易得出来,如果置换0为 ( 1 2 . . . n 1 2 . . . n ) \begin{pmatrix} 1&2 &... &n\\1 &2 &... &n\end{pmatrix} (1122......nn)的话,那么置换i的循环节数是 g c d ( n , i ) gcd(n,i) gcd(n,i),根据Polya定理得到:
L = 1 n ∑ i = 1 n n g c d ( i , n ) L=\frac{1}{n}\sum_{i=1}^n n^{gcd(i,n)} L=n1∑i=1nngcd(i,n)
= 1 n ∑ d ∣ n n d ∑ i = 1 n [ g c d ( i , n ) = d ] =\frac{1}{n}\sum_{d|n}n^d\sum_{i=1}^n[gcd(i,n)=d] =n1∑d∣nnd∑i=1n[gcd(i,n)=d]
= ∑ d ∣ n n d − 1 ∑ i = 1 n [ g c d ( i / d , n / d ) = 1 ] =\sum_{d|n}n^{d-1}\sum_{i=1}^n[gcd(i/d,n/d)=1] =∑d∣nnd−1∑i=1n[gcd(i/d,n/d)=1]
= ∑ d ∣ n n d − 1 ∑ i = 1 n / d [ g c d ( i , n / d ) = 1 ] =\sum_{d|n}n^{d-1}\sum_{i=1}^{n/d}[gcd(i,n/d)=1] =∑d∣nnd−1∑i=1n/d[gcd(i,n/d)=1]
= ∑ d ∣ n ϕ ( n / d ) n d − 1 =\sum_{d|n}\phi(n/d)n^{d-1} =∑d∣nϕ(n/d)nd−1
代码:
#include
#include
#include
#include
using namespace std;
int read() {
int q=0;char ch=' ';
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
return q;
}
const int N=100005;
int T,n,mod,ans,tot,is[N],pri[N];
void init() {
for(int i=2;i<=100000;++i) {
if(!is[i]) pri[++tot]=i;
for(int j=1;j<=tot&&pri[j]*i<=100000;++j) {
is[pri[j]*i]=1;
if(!i%pri[j]) break;
}
}
}
int ksm(int x,int y) {
int re=1;x%=mod;
while(y) {
if(y&1) re=re*x%mod;
x=x*x%mod,y>>=1;
}
return re;
}
int phi(int x) {
int re=x;
for(int i=1;pri[i]*pri[i]<=x;++i) if(!(x%pri[i])){
re=re-re/pri[i];
while(!(x%pri[i])) x/=pri[i];
}
if(x!=1) re=re-re/x;
return re%mod;
}
int main() {
init(),scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&mod);ans=0;
for(int i=1;i*i<=n;++i) if(!(n%i)) {
ans+=phi(i)*ksm(n,n/i-1)%mod,ans%=mod;
if(i*i!=n) ans+=phi(n/i)*ksm(n,i-1)%mod,ans%=mod;
}
printf("%d\n",ans);
}
return 0;
}
题目大意:给你12条用6种以下颜色染色的棍子,问可以组成多少本质不同的正方体
题目分析:
可以假设那是一个骰子,以某一个数字为上面,一个数字为前面,所以共有 6 ∗ 4 = 24 6*4=24 6∗4=24种旋转。
这24种旋转为:
1.不旋转,1种,12个循环节,长度为1
2.通过两个对立的顶点旋转120°和240°,共8种,4个循环节,长度为3
3.通过两个对立面的中心旋转90°或270°,共6种,3个循环节,长度为4
4.通过两个对立面的中心旋转180°,共3种,6个循环节,长度为2
5.通过两条对立棱的中心旋转180°,共6种,2个循环节长度为1,5个循环节长度为2
然后每组情况,可以用组合数学搞一搞即可。
#include
#include
#include
#include
using namespace std;
#define LL long long
int T;
int a[8],b[8];LL c[15][15];
LL work(LL x) {//循环节长度为x
LL re=1,js=0;
for(int i=1;i<=6;++i)
if(!(a[i]%x)) b[i]=a[i]/x,js+=b[i];
else return 0;
for(int i=1;i<=6;++i) re*=c[js][b[i]],js-=b[i];
return re;
}
LL rot_edge() {//单独处理通过两条对立棱的中心旋转的情况
LL re=0;
for(int i=1;i<=6;++i)//枚举在长度为1循环节里的两条边
for(int j=1;j<=6;++j)
if(a[i]&&a[j]) --a[i],--a[j],re+=work(2),++a[i],++a[j];
return 1LL*6*re;
}
void init() {
for(int i=0;i<=12;++i) {
c[i][0]=1;
for(int j=1;j<=i;++j) c[i][j]=c[i-1][j-1]+c[i-1][j];
}
}
int main() {
scanf("%d",&T);init();
while(T--) {
for(int i=1;i<=6;++i) a[i]=0;
for(int i=1;i<=12;++i) {int x;scanf("%d",&x),++a[x];}
LL ans=work(1)+1LL*8*work(3)+1LL*3*work(2)+1LL*6*work(4)+rot_edge();
printf("%lld\n",ans/(1LL*24));
}
return 0;
}
题解戳我QWQ