万事先吐槽:为什么我在这个专题疯狂被卡常啊
群论这玩意是真的不接地气。刚开始听的时候这是个什么玩意啥也听不懂啊。。。
然而其实有几个概念,显得很高端而已。(下面开始抄理解深刻的(他自己说的)$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 }