题解 P2144 【[FJOI2007]轮状病毒】
一开始我看到这个就像直接上一个
接着我用分数来优化高精度(显然不行);
接着我打表找规律(并没有发现什么)。
于是只能推式子了。
考虑把先不管中心点,然后把外围的
于是方案数就类似一个整数拆分,将外围的点分成若干个联通块,
即设
但是我们还需要考虑上第一个点与最后一个点连边的情况,发现,如果分配第一个联通块大小为
于是答案的计算方式就等于
再套个高精度,复杂为
本文认为此题高精度近似
#include <cstdio>
#include <cstring>
#define R register
#define Max(_A, _B) (_A > _B ? _A : _B)
const int Mod = 1e8;
struct BigNum
{
int a[110], len;
BigNum(){ len = 1; }
friend BigNum operator + (R BigNum A, R BigNum B)
{
A.len = Max(A.len, B.len);
for(R int i = 0; i < A.len; i++)
{
R int tmp = A.a[i] + B.a[i];
A.a[i] = tmp % Mod;
A.a[i + 1] += tmp / Mod;
}
while(A.a[A.len]) A.len++;
return A;
}
BigNum operator * (R int K)
{
R BigNum T;
memset(T.a, 0, sizeof(T.a)); T.len = len;
for(R int i = 0; i < len; i++)
{
R long long tmp = 1ll * a[i] * K + T.a[i];
T.a[i + 1] += tmp / Mod;
T.a[i] = tmp % Mod;
}
while(T.a[T.len]) T.len++;
return T;
}
void Print()
{
printf("%d", a[len - 1]);
for(R int i = len - 2; i >= 0; i--) printf("%.8d", a[i]);
puts("");
}
} f[110];
int n;
int main()
{
scanf("%d", &n);
f[0].a[0] = 1;
for(R int i = 0; i < n; i++)
for(R int j = 1; i + j <= n; j++)
if(i == 0) f[i + j] = f[i + j] + f[i] * (j * j);
else f[i + j] = f[i + j] + f[i] * j;
f[n].Print();
return 0;
}