题目大意: 有 n ( n + 1 ) 2 \frac {n(n+1)} 2 2n(n+1) 个六边形瓷砖,第一层有 1 1 1 个,第二层有 2 2 2 个,以此类推组成一个三角形,给每块瓷砖染黑色或白色,两种染色方案相同当且仅当一种方案通过旋转或翻转得到另一种方案。
题解
明显的burnside定理,一共有
6
6
6 中置换,不动
,转120度
,转240度
,以及三种不同方向的翻折
。
不动:循环长度为 1 1 1。
旋转:循环长度为 3 3 3,但是有可能中间多出 1 1 1 块瓷砖,那么这块瓷砖怎么转都不会变,所以它的循环长度为 1 1 1。
翻折:除了位于正中间的点他们循环长度为 1 1 1,其它点循环长度为 2 2 2。
对于同一个循环内的瓷砖,他们的颜色都相同,要么黑要么白,一共两种情况。
再套一个高精度模板即可。
代码如下:
#include <cstdio>
#include <cstring>
#define ll long long
int n,m;
struct GJD{
int len,a[410];
GJD():len(1){memset(a,0,sizeof(a));}
void jinwei()
{
for(int i=1;i<=len;i++)
if(a[i]>9)
{
a[i+1]+=a[i]/10;
a[i]%=10;
if(i==len)len++;
}
}
void operator +=(const GJD b)
{
if(b.len>len)len=b.len;
for(int i=1;i<=len;i++)a[i]+=b.a[i];
jinwei();
}
GJD operator *(const int b)
{
GJD re;re.len=len;
for(int i=1;i<=len;i++)re.a[i]=a[i]*b;
re.jinwei();
return re;
}
GJD operator *(const GJD b)
{
GJD re;re.len=len+b.len-1;
for(int i=1;i<=len;i++)
for(int j=1;j<=b.len;j++)
re.a[i+j-1]+=a[i]*b.a[j];
re.jinwei();
return re;
}
}two[410],ans;
int main()
{
scanf("%d",&n);m=n*(n+1)/2;
two[0].a[1]=1;
for(int i=1;i<=400;i++)two[i]=two[i-1]*2;
ans+=two[m];
ans+=(two[m/3]*2)*(m%3>0?2:1);
ans+=(two[(m-(n+1)/2)/2]*two[(n+1)/2])*3;
int last=0;
for(int i=ans.len;i>=1;i--)
ans.a[i]+=last*10,last=ans.a[i]%6,ans.a[i]/=6;
while(!ans.a[ans.len])ans.len--;
for(int i=ans.len;i>=1;i--)printf("%d",ans.a[i]);
}