题解 P1743 【矩阵 III】

皎月半洒花

2018-11-03 18:51:42

Solution

这个题还可以吧……大约普及组T3难度(~~虽然我并不知道什么难度是普及难度…~~) _____ 前置技能: $$\sum i = n(n + 1)/2$$ $$\sum i^2 = \frac{n\cdot(n + 1) \cdot(2n+1)}{6}$$ $$\sum i^3 = (\sum i )^2 = \frac{n^2(n+1)^2}{4}$$ 其中$i \in [1,N]$且$i \in \mathbb Z$ _____ 这个题最麻烦的地方是推式子而已,其余的直接$long ~double$爆算即可。 但是爆算也是有技巧的,我们发现$n$很大,$m$很小只有$4$,所以我们分类讨论即可。 哦,忘记了,这个题的$n \& m$都是指格的数量而不是点的数量,所以我们处理点时要$++n$ 之后说正解: * 当$m=0$时,此时只有一排点,只可以向下走,所以方案数为$1$ * 当$m=1$时,此时有两列点,因为我们为了到终点是必须向右走的,而我们可以从任意一行选择向右走——因为不能返回,所以方案数为$n$ * 当$m=2$时,我们可以把它转化为$m=1$的情况,即每到一个点都可以向右走从而到达了$m=1$的局面,那么总答案就是$$\sum \limits _{i=1}^{n}i = \frac{n \times(n+1)}{2}$$ * 同理,当$m=3$时继续转化,我们的答案就是$$\sum \sum i(i \in [1,N] \&i\in \mathbb Z) = \frac{n(n+1)(2n+1)}{12} + \frac{n(n+1)}{4}$$ * 那么最后$n=4$的情况下,我们继续转化: $$Ans = \sum \sum \sum i = \frac{n(n+1) + 2 \cdot n(n+1)(2n+1)+ n^2(n+1)^2}{24} + \frac{n(n+1)}{8}$$ 然后本题就是$O(1)$的了。 之后我们要**保留前17位有效数字**,由于本题数据神坑,(迄今为止)未说明保留17位有效数字,所以十分$GG$…… 那我们最后算出来的是一个科学计数法,所以我们要手写输出,用一个栈即可。 ```cpp const double eps = 1 ; inline void Print(long double A){ int cnt = 0 ; long double B, T ; while (A > eps) B = floorl(A / 10), T = A - B * 10, S.push((int)(T)), A /= 10 ; while (!S.empty()){ ++ cnt ; if (cnt <= 17) printf("%d", S.top()), S.pop() ; else printf("0"), S.pop() ; } } ``` 注意$eps=1$这个东西……因为我们要的是整数位$233$ 完整代码: ```cpp #include <cmath> #include <stack> #include <cstdio> #include <iostream> using namespace std ; stack <int> S ; const double eps = 1 ; long double Ans ; long long N, M ; inline void Print(long double A){ int cnt = 0 ; long double B, T ; while (A > eps) B = floorl(A / 10), T = A - B * 10, S.push((int)(T)), A /= 10 ; while (!S.empty()){ ++ cnt ; if (cnt <= 17) printf("%d", S.top()), S.pop() ; else printf("0"), S.pop() ; } } int main(){ cin >> N >> M ; ++ N ; if (M == 0) cout << "1" << endl ; else if (M == 1) cout << N << endl ; else if (M == 2) Print(N * (N + 1) / 2) ; else if (M == 3){ Ans = (long double)N * (long double)(N + 1) * (long double) (2 * N + 1) / 12 ; Ans += N * (N + 1) / 4 ; Print(Ans + 0.5) ; } else if (M == 4){ Ans += (long double)N * (long double)(N + 1.0) + (long double)N * 2.0 * (long double)(N + 1.0) * (long double)(2 * N + 1.0) ; Ans += (long double)N * (long double)N * (long double)(N + 1.0) * (long double)(N + 1.0) + (long double)(N * 3.0) * (long double)(N + 1) ; Ans = Ans / 24.0 ; Print(Ans + 0.5) ; } return 0 ; } ```