万事先吐槽:为什么我在这个专题疯狂被卡常啊

群论这玩意是真的不接地气。刚开始听的时候这是个什么玩意啥也听不懂啊。。。

然而其实有几个概念,显得很高端而已。(下面开始抄理解深刻的(他自己说的)$yxs$的博客

所谓的置换,其实就是把元素换位置。

置换群$G$就是一堆置换,满足存在逆元和单位元(不动呗),有结合律,封闭性。。。

不动点就是某一个置换$i$中有多少个元素位置并没有改变,称为$c_i$。

$k$不动置换类就是所有使$k$位置元素位置不变的置换的集合,称为$Z_k$

等价类就是元素$k$在任意置换后可能出现的位置集合,称为$E_k$

根据含义可知等价类之间没有交集,它们的并集是全集。等价类的数目称为$L$

 

然后就有了烧边$Burnside$引理:$L=\frac{\sum c_i}{|G|}$。就是不动点的平均值。

然而我不会也不想证明。。。这个东西没什么扩展性,记结论差不多就够了

如果哪天需要了,被打脸了就上去看群论之神的博客就好了。

以及还有$Burnside$的具体应用$Polya$。如果没有元素个数等限制的话:

$L=\frac{\sum m^{h_i}}{|G|}$

其中$m$是可以染的颜色种数,$h_i$表示元素$i$所在的循环节个数,其实也就是总置换数除以循环节长度。

然后记住结论就可以做题了。

 

因为理解很不深刻所以做这些题非常艰难,然后还颓了不少题解。。。在$yxm$说是水水水的题目上。

只能说,和$CSP-S \ 390+$的所有大佬们显然还是有双重巨大的差距啊。。。

 

题目顺序按照知识点的深浅排序,也是推荐的做题顺序。大致是难度排序。

(如果做题顺序反了的话,基本就要想我一样一路颓题解下来了)

 

Cards:

$Description:$

小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗成另一种.Sun发现这个问题有点难度,决定交给你,答案可能很大,只要求出答案除以P的余数(P为质数).$Max{Sr,Sb,Sg}<=20,m<=60,m+1<p<100,n=Sr+Sb+Sg$

输入数据保证任意多次洗牌都可用这 m种洗牌法中的一种代替,且对每种洗牌法,都存在一种洗牌法使得能回到原状态。

其实我觉得题还不错,再看一遍又不会了。。。我还是有必要讲一讲的。

因为对总数有限制,所以不能$Polya$,所以选择去烧个边。

首先,题目中的洗牌法并不存在单位元,所以我们强制加入一种“洗牌法”是所有牌都不变。

数据范围很小,对于每种洗牌法我们都可以暴力算出循环节大小与个数。

对于每个循环节进行$dp$,每个循环节都要染成相同的颜色。

然后就可以统计答案了。其实有点像个二维背包。

别忘了烧边的时候最后答案要去掉置换群的大小,因为$p$是质数而且出题人仁慈的保证了$m+1<p$所以$exgcd$或快速幂乱写都行。

 1 #include<cstdio>
 2 #define n (r+b+g)
 3 int pp,q[61][61],r,b,g,m,p,al[61],cir[61],cnt_cir,dp[61][21][21],ans,x,y,siz[61];
 4 void ex_gcd(int a,int b,int &x,int &y){
 5     if(!b){x=1;y=0;return;}
 6     ex_gcd(b,a%b,x,y);
 7     int res=x;x=y;y=res-a/b*x;
 8 }
 9 int main(){
10     scanf("%d%d%d%d%d",&r,&b,&g,&m,&p);
11     for(int i=1;i<=m;++i) for(int j=1;j<=n;++j) scanf("%d",&q[i][j]);
12     for(int i=1;i<=n;++i) q[0][i]=i;
13     dp[0][0][0]=1;
14     for(int w=0;w<=m;++w){
15         cnt_cir=0;
16         for(int i=1;i<=n;++i)al[i]=0;
17         for(int i=1;i<=n;++i)if(!al[i]){
18             cnt_cir++; siz[cnt_cir]=1; pp=i; al[pp]=1;
19             while(!al[q[w][pp]]) al[q[w][pp]]=1, siz[cnt_cir]++, pp=q[w][pp];
20         }
21         for(int i=1;i<=cnt_cir;++i)for(int j=0;j<=r;++j)for(int k=0;k<=b;++k)dp[i][j][k]=0;
22         for(int i=1;i<=cnt_cir;++i)for(int j=r;j>=0;--j)for(int k=b;k>=0;--k){
23             (dp[i][j][k]+=dp[i-1][j][k])%=p;
24             if(j>=siz[i])(dp[i][j][k]+=dp[i-1][j-siz[i]][k])%=p;
25             if(k>=siz[i])(dp[i][j][k]+=dp[i-1][j][k-siz[i]])%=p;
26         }
27         (ans+=dp[cnt_cir][r][b])%=p;
28     }
29     ex_gcd(m+1,p,x,y);
30     x=(x%p+p)%p;
31     printf("%d\n",ans*x%p);
32 }
View Code

相关文章: