bzoj 1002 [FJOI2007]輪狀病毒 Matrix-Tree定理+遞推
阿新 • • 發佈:2018-08-14
c++ 無向圖 tps pan n+1 ref out 高精 clu
題面
題目傳送門
解法
求無向圖生成樹個數,可以直接通過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; }
bzoj 1002 [FJOI2007]輪狀病毒 Matrix-Tree定理+遞推