[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]);
}
posted @ 2022-03-23 15:48  leiyuanze  阅读(37)  评论(0编辑  收藏  举报