Burnside引理和Polya定理相关题集
LCS HDU-5495
题意
给两个序列:\(\{a_1,a_2,\cdots,a_n\}\),\(\{b_1,b_2,\cdots,b_n\}\) ,都是 \(\{1,2,3,\cdots,n \}\) 的一个排列。求出一个序列 \(p\) ,使得 \(a_{p_1},a_{p_2},\cdots,a_{p_n}\) 和 \(b_{p_1},b_{p_2},\cdots,b_{p_n}\) 的 \(\text{LCS}\) 最大。输出该 \(\text{LCS}\) 的值。
分析
对 \(a_i->b_i\) 建边,最终总能形成一个环,对于这个长度为 \(L\) 的环,我们总能找到一个长度为 \(L-1\) 的 \(\text{LCS}\)。所以,我们只要用序列的长度减去长度大于 \(1\) 的环的个数就是最终的结果。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N],nxt[N];
bool vis[N];
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
int ans=0,b;
scanf("%d",&n);
for(int i=1;i<=n;i++)
vis[i]=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
scanf("%d",&b);
nxt[a[i]]=b;
}
for(int i=1;i<=n;i++)
{
if(!vis[a[i]])
{
int x=a[i],cnt=0;
while(!vis[x])
{
vis[x]=1;
x=nxt[x];
cnt++;
}
ans+=cnt;//cout<<"cnt="<<cnt<<endl;
if(cnt>1) ans--;
}
}
printf("%d\n",ans);
}
return 0;
}
Count the Tetris HDU-1812
Let it Bead POJ-2409
题意
给出 \(c\) 种颜色的珍珠,每种的数量无限,组成长为 \(s\) 的项链。问可以组成多少种不同的项链。\(cs\leq 32\)
分析
Polya定理模板题,直接套公式。设 \(\{a_1,a_2,\cdots,a_{|G|} \}\) 是 \({1,2,\cdots,n}\) 上的置换群,现用 \(m\) 种颜色对这 \(n\) 个点染色,则不同的染色方案有:
\[ANS=\frac{(m^{c_1}+m^{c_2}+\cdots+m^{c_{|G|}})}{|G|}
\]
其中,\(c_k\) 为置换 \(a_k\) 中轮换的个数,即循环节的个数。
常见置换的轮换个数:
- 旋转:\(n\) 个点顺时针旋转 \(i\) 个位置的置换,轮换的个数为:\(gcd(i,n)\);
- 翻转:\(n\) 为偶数且对称轴不过顶点:\(\frac{n}{2}\),\(n\) 为偶数且对称轴过顶点:\(\frac{n}{2}+1\),\(n\) 为奇数:\(\frac{n+1}{2}\);
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
ll power(ll a,int b)
{
ll res=1;
while(b)
{
if(b&1) res=res*a;
a=a*a;
b>>=1;
}
return res;
}
int main()
{
int c,s;
while(scanf("%d%d",&c,&s)!=EOF)
{
if(c==0&&s==0) break;
if(c==0||s==0) printf("0\n");
ll ans=0;
int m=2*s;
for(int i=1;i<=s;i++)
ans+=power(1LL*c,gcd(i,s));
if(s&1)
ans+=1LL*s*power(1LL*c,(s+1)/2);
else
{
ans+=1LL*s/2*power(1LL*c,s/2);
ans+=1LL*s/2*power(1LL*c,s/2+1);
}
printf("%lld\n",ans/m);
}
return 0;
}
Necklace of Beads POJ-1286
分析
模板题,同上。