[AHOI2002]黑白瓷砖
\(\text{Solution}\)
根据 \(Polya\) 定理推算
记总砖数为 \(m = \frac{n(n+1)}2\)
考虑旋转,不动点数均为为 \(2^{\frac{m+2}3}\)
翻转,考虑三个对角线,记对称轴上砖数为 \(s=\frac{n+1}2\),则不动点数均为 \(2^{\frac{m-s}2+s}\)
还有 \(2^m\)
故答案为三种相加除以 \(6\)
加上高精度即可
\(\text{Code}\)
#include <cstdio>
#include <cstring>
#include <iostream>
#define RE register
#define IN inline
using namespace std;
int n, m;
struct BigInt{
int a[1005], n;
IN BigInt(){n = 0; memset(a, 0, sizeof a);}
IN BigInt operator + (const BigInt &b)
{
BigInt c; c.n = max(n, b.n);
for(RE int i = 1; i <= c.n; i++)
c.a[i + 1] += (c.a[i] + a[i] + b.a[i]) / 10,
c.a[i] = (c.a[i] + a[i] + b.a[i]) % 10;
while (c.a[c.n + 1]) ++c.n;
return c;
}
IN BigInt operator * (const BigInt &b)
{
BigInt c; c.n = n + b.n - 1;
for(RE int i = 1; i <= n; i++)
for(RE int j = 1; j <= b.n; j++)
c.a[i + j] += (c.a[i + j - 1] + a[i] * b.a[j]) / 10,
c.a[i + j - 1] = (c.a[i + j - 1] + a[i] * b.a[j]) % 10;
while (c.a[c.n + 1]) ++c.n;
return c;
}
IN BigInt operator / (const int &b)
{
BigInt c; c.n = n;
for(RE int i = 1; i <= n; i++) c.a[i] = a[i];
for(RE int i = n; i; i--)
c.a[i - 1] += c.a[i] % b * 10, c.a[i] /= b;
while (!c.a[c.n] && c.n > 1) --c.n;
return c;
}
};
IN BigInt fpow(BigInt x, int y)
{
BigInt s; s.n = 1, s.a[1] = 1;
for(; y; y >>= 1, x = x * x) if (y & 1) s = s * x;
return s;
}
int main()
{
scanf("%d", &n), m = n * (n + 1) / 2;
BigInt _2, _3; _2.n = _3.n = 1, _2.a[1] = 2, _3.a[1] = 3;
BigInt ans = fpow(_2, m) + fpow(_2, (m - (n + 1) / 2) / 2 + (n + 1) / 2) * _3;
ans = (ans + fpow(_2, (m + 2) / 3) * _2) / 6;
for(RE int i = ans.n; i; i--) printf("%d", ans.a[i]);
}