【BZOJ1002】【FJOI2007】轮状病毒
2018-01-12 11:10
260 查看
【题目链接】
点击打开链接
【思路要点】
输入与输出仅包含一个数,考虑找规律。
使用欧几里得算法配合\(Matrix-Tree\)定理求解取模一个大质数下问题的答案,并打表。
结果如下\(F(1)=1,F(2)=8,F(3)=16,F(4)=45,F(5)=121,F(6)=320,F(7)=841,F(8)=2205\)。
发现规律,\(F(i)=3*F(i-1)-F(i-2)+2(i≥5)\)。
递推即可,需要实现一个高精度类。
时间复杂度\(O(N*LogAns)\)。
【代码】
点击打开链接
【思路要点】
输入与输出仅包含一个数,考虑找规律。
使用欧几里得算法配合\(Matrix-Tree\)定理求解取模一个大质数下问题的答案,并打表。
结果如下\(F(1)=1,F(2)=8,F(3)=16,F(4)=45,F(5)=121,F(6)=320,F(7)=841,F(8)=2205\)。
发现规律,\(F(i)=3*F(i-1)-F(i-2)+2(i≥5)\)。
递推即可,需要实现一个高精度类。
时间复杂度\(O(N*LogAns)\)。
【代码】
/*Program till Line 65*/ #include<bits/stdc++.h> using namespace std; #define MAXN 505 template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } struct INT {int len, value[MAXN]; } a[MAXN]; INT operator + (INT a, INT b) { INT res; res.len = max(a.len, b.len); memset(res.value, 0, sizeof(res.value)); for (int i = 0; i <= res.len; i++) res.value[i] = a.value[i] + b.value[i]; for (int i = 0; i <= res.len; i++) { res.value[i + 1] += res.value[i] / 10; res.value[i] %= 10; } if (res.value[res.len + 1]) res.len++; return res; } INT operator - (INT a, INT b) { INT res; res.len = a.len; memset(res.value, 0, sizeof(res.value)); for (int i = 0; i <= res.len; i++) res.value[i] = a.value[i] - b.value[i]; for (int i = 0; i <= res.len; i++) if (res.value[i] < 0) { res.value[i] += 10; res.value[i + 1]--; } while (res.value[res.len] == 0) res.len--; return res; } INT number(int x) { INT res; res.len = 0; memset(res.value, 0, sizeof(res.value)); while (x) { res.value[++res.len] = x % 10; x /= 10; } return res; } void print(INT x) { for (int i = x.len; i >= 1; i--) printf("%d", x.value[i]); printf("\n"); } int main() { int n; read(n); a[1] = number(1); a[2] = number(8); a[3] = number(16); a[4] = number(45); for (int i = 5; i <= n; i++) a[i] = a[i - 1] + a[i - 1] + a[i - 1] - a[i - 2] + number(2); print(a ); return 0; } /*Use the program below to print a form of answer*/ /*1 8 16 45 121 320 841 2205*/ #include<bits/stdc++.h> using namespace std; #define MAXN 505 #define P 1000000007 template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } long long a[MAXN][MAXN]; long long calc(int n) { int f = 1; for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) if (a[j][i]) { if (i != j) { swap(a[i], a[j]); f = -f; } break; } if (a[i][i] == 0) return 0; for (int j = 1; j <= n; j++) { if (j == i || a[j][i] == 0) continue; while (a[j][i]) { swap(a[i], a[j]); f = -f; long long tmp = a[j][i] / a[i][i]; for (int k = 1; k <= n; k++) a[j][k] = (a[j][k] - a[i][k] * tmp % P + P) % P; } } } long long ans = 1; for (int i = 1; i <= n; i++) ans = ans * a[i][i] % P; if (f == 1) return ans; else return (P - ans) % P; } int main() { int n; read(n); if (n == 1) { printf("1\n"); return 0; } a[0][0] = n; for (int i = 1; i <= n; i++) { a[i][i] = 3; a[0][i] = a[i][0] = P - 1; } for (int i = 1; i <= n - 1; i++) a[i + 1][i] = a[i][i + 1] = P - 1; a[1] = a [1] = P - 1; printf("%lld\n", calc(n)); return 0; }
相关文章推荐
- [高精度][BZOJ1002][FJOI2007]轮状病毒
- 【BZOJ1002】【FJOI2007】轮状病毒(生成树计数)
- bzoj1002: [FJOI2007]轮状病毒
- 【bzoj1002】[FJOI2007]轮状病毒
- BZOJ 1002 FJOI2007 轮状病毒 递推+高精度
- bzoj 1002: [FJOI2007]轮状病毒
- [行列式计算]BZOJ1002: [FJOI2007]轮状病毒
- 【bzoj1002】[FJOI2007]轮状病毒
- [bzoj1002] [FJOI2007]轮状病毒
- BZOJ 1002 [FJOI2007]轮状病毒
- BZOJ 1002([FJOI2007]轮状病毒-基尔霍夫矩阵)
- BZOJ 1002 [FJOI2007] 轮状病毒
- BZOJ 1002: [FJOI2007]轮状病毒【数学题】
- BZOJ 1002: [FJOI2007]轮状病毒
- 【BZOJ】1002: [FJOI2007]轮状病毒(DP+规律+高精度)
- BZOJ 1002:[FJOI2007] 轮状病毒 (基尔霍夫矩阵生成树定理)
- Bzoj1002 [FJOI2007]轮状病毒
- bzoj1002:[FJOI2007]轮状病毒
- bzoj 1002 FJOI2007 轮状病毒 题解
- [Bzoj1002][FJOI2007]轮状病毒