bzoj 1002 [FJOI2007]轮状病毒 Matrix-Tree定理+递推
题面
解法
求无向图生成树个数,可以直接通过Matrix-Tree定理求
但是\(n≤100\),精度肯定爆了
所以先打个表找个规律:
\(1,5,16,45,121,320,841…\)
可以发现,奇数项感觉都是完全平方数,偶数项和完全平方数似乎也有点关系
仔细研究表,发现\(F_i=f_i^2-4((n+1)\%2)\),其中\(f_1=1,f_2=3,f_i=f_{i-2}+f_{i-1}\)
高精度一下即可
代码
#include <bits/stdc++.h>
#define N 110
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
x = 0; int f = 1; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
string f[N], F[N];
string operator ^ (string x, string y) {
int l1 = x.size() - 1, l2 = y.size() - 1;
if (l1 > l2) swap(x, y), swap(l1, l2);
for (int i = 1; i <= l2 - l1; i++) x = '0' + x;
string ret = ""; int k = 0;
for (int i = l2; ~i; i--) {
int t = (x[i] - '0') + (y[i] - '0') + k;
if (t > 9) t -= 10, k = 1; else k = 0;
ret = (char)(t + '0') + ret;
}
if (k) ret = '1' + ret; return ret;
}
string operator - (string x, string y) {
int l1 = x.size() - 1, l2 = y.size() - 1;
for (int i = 1; i <= l1 - l2; i++) y = '0' + y;
string ret = ""; int k = 0;
for (int i = l1; i >= 0; i--) {
int t = (x[i] - '0') - (y[i] - '0') - k;
if (t < 0) t += 10, k = 1; else k = 0;
ret = (char)(t + '0') + ret;
}
while (ret.size() > 1 && ret[0] == '0') ret.erase(ret.begin());
return ret;
}
string operator * (string x, string y) {
int l1 = x.size(), l2 = y.size();
int a[210] = {0}, b[210] = {0}, c[410] = {0};
for (int i = 0; i < l1; i++) a[l1 - i - 1] = x[i] - '0';
for (int i = 0; i < l2; i++) b[l2 - i - 1] = y[i] - '0';
for (int i = 0; i < l1; i++)
for (int j = 0; j < l2; j++)
c[i + j] += a[i] * b[j];
for (int i = 0; i <= l1 + l2; i++)
c[i + 1] += c[i] / 10, c[i] %= 10;
string ret = "";
for (int i = 0; i <= l1 + l2; i++) ret = (char)(c[i] + '0') + ret;
while (ret.size() > 1 && ret[0] == '0') ret.erase(ret.begin());
return ret;
}
int main() {
int n; read(n);
f[1] = "1", f[2] = "3";
for (int i = 3; i <= n; i++) f[i] = f[i - 1] ^ f[i - 2];
for (int i = 1; i <= n; i++) {
F[i] = f[i] * f[i];
if (i % 2 == 0) F[i] = F[i] - "4";
}
cout << F[n] << "\n";
return 0;
}