BZOJ 4005 [JLOI 2015] 骗我呢

首先,我们可以得到:每一行的数都是互不相同的,所以每一行都会有且仅有一个在 $[0, m]$ 的数没有出现。

我们可以考虑设 $Dp[i][j]$ 为处理完倒数 $i$ 行,倒数第 $i$ 行缺的数字是 $j$ 的方案数。

那么就有:

$$Dp[i][j] = \sum_{k=max(0,j-1)}^{m}Dp[i - 1][k]$$

自己画一画图就可以明白了,在这里就不解释了。毕竟 Gromah 太懒($ru\grave{o}$)

然后我们考虑把这个转移图画出来:

然后就是求这个图中从右上到左下的路径条数嘛。(每次只能往左或者是往右下或者是往下)

转化一下,实际上就是求这个东西:

从 $(0,0)$ 到 $(n*2+m+1,m+1)$,每次可以 $x+1,y-1$ 或者 $x+1,y+1$,并且不穿过 $y=0$ 和 $y=m+1$ 这两条直线的路径条数。

首先,全集是 ${n*2+m+1 \choose m+1}$,

然后我们算穿过 $y=0$ 的路径条数,既然穿过 $y=0$ 就必然经过 $y=-1$,于是我们让终点和 $y=m+2$ 这条直线沿着 $y=-1$ 翻转,

然后就可以算出 $(0,0)$ 到翻转之后的终点的路径条数。

于是还没完。还有那些先穿过 $y=0$ 再又穿过 $y=m+1$ 这条直线的路径我们要加回来。。。

于是又把坐标系沿着翻转之后的 $y=m+2$ (此时应该是 $y=-m-4$ 了)再次翻转。再统计答案。。。

直到方案为 $0$ 了为止。

计算穿过 $y=m+1$ 的路径条数同理。。。

我知道我语言表达能力及其低下,所以还是上代码好了。。。

 1 #include <cmath> 
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long LL;
 8 #define N 3000000
 9 #define Mod 1000000007
10 
11 int n, m, ans = 0;
12 int Fac[N + 1], Inv[N + 1];
13 
14 inline int power(int u, int v)
15 {
16     int res = 1;
17     for (; v; v >>= 1)
18     {
19         if (v & 1) res = (LL) res * u % Mod;
20         u = (LL) u * u % Mod;
21     }
22     return res;
23 }
24 
25 inline void Prepare()
26 {
27     Fac[0] = Inv[0] = 1;
28     for (int i = 1; i <= N; i ++)
29         Fac[i] = (LL) Fac[i - 1] * i % Mod;
30     Inv[N] = power(Fac[N], Mod - 2);
31     for (int i = N - 1; i ; i --)
32         Inv[i] = (LL) Inv[i + 1] * (i + 1) % Mod;
33 }
34 
35 inline int C(int u, int v)
36 {
37     if (u < 0 || v < 0 || u < v) return 0;
38     return (LL) Fac[u] * Inv[v] % Mod * Inv[u - v] % Mod;
39 }
40 
41 inline int T(int u, int v)
42 {
43     if (u < abs(v)) return 0;
44     return C(u, u - abs(v) >> 1);
45 }
46 
47 inline int Inc(int u, int v)
48 {
49     return u + v - (u + v >= Mod ? Mod : 0);
50 }
51 
52 int main()
53 {
54     #ifndef ONLINE_JUDGE
55         freopen("4005.in", "r", stdin);
56         freopen("4005.out", "w", stdout);
57     #endif
58     
59     Prepare();
60     scanf("%d%d", &n, &m);
61     int x = n * 2 + m + 1;
62     ans = T(x, m + 1);
63     
64     for (int y = m + 1, y_1 = -1, y_2 = m + 2; x >= abs(y); )
65     {
66         y = 2 * y_1 - y;
67         y_2 = 2 * y_1 - y_2;
68         ans = Inc(ans, Mod - T(x, y));
69         y = 2 * y_2 - y;
70         y_1 = 2 * y_2 - y_1;
71         ans = Inc(ans, T(x, y));
72     }
73     
74     for (int y = m + 1, y_1 = m + 2, y_2 = -1; x >= abs(y); )
75     {
76         y = 2 * y_1 - y;
77         y_2 = 2 * y_1 - y_2;
78         ans = Inc(ans, Mod - T(x, y));
79         y = 2 * y_2 - y;
80         y_1 = 2 * y_2 - y_1;
81         ans = Inc(ans, T(x, y));
82     }
83     
84     printf("%d\n", ans);
85     
86     #ifndef ONLINE_JUDGE
87         fclose(stdin);
88         fclose(stdout);
89     #endif
90     return 0;
91 }
4005_Gromah

 

posted @ 2015-04-28 22:03  Gromah  阅读(1373)  评论(0编辑  收藏  举报