1 条题解

  • 0
    @ 2026-8-3 14:00:16

    首先需要田忌至少赢 aa 场,也就是说:

    • 田忌第 aa 好的马至少要能打败齐威王最坏的马。
    • 田忌第 a−1a - 1 好的马至少要能打败齐威王的两匹马,因为有一匹要留给第 aa 好的马。
    • ……
    • 田忌最好的马至少要能打败齐威王的 aa 匹马,因为有 a−1a - 1 匹要留给前面 a−1a - 1 匹马。

    齐威王也需要至少赢 bb 场,分析过程同上。

    以 (0,0)(0, 0) 为起点,从快到慢考虑每一匹马,对田忌的马向右走一格,对齐威王的马向上走一格,则最终要求走到 (a+b,a+b)(a + b, a + b) 且不穿过 y=x+by = x + b 和 y=x−ay = x - a 两条直线。

    以 y=x+by = x + b 为例,将第一次穿过该直线后向右的向上的移动交换,可以发现它和 (0,0)(0, 0) 按相同规则走到 (a−1,a+2b+1)(a - 1, a + 2b + 1) 的路径一一对应。

    对 y=x−ay = x - a 的分析同上,并且不难发现两条直线不可能同时被穿过,因此从总路径数中扣除穿过这两条直线的不合法路径数就可以得到最终答案:

    $$C _{2a + 2b} ^{a + b} - C _{2a + 2b} ^{a - 1} - C _{2a + 2b} ^{b - 1} = \dbinom{2a + 2b}{a + b} - \dbinom{2a + 2b}{a - 1} - \dbinom{2a + 2b}{b - 1}$$
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 4e6 + 12, Real_N = 4e6, P = 1e9 + 7;
    int f1[N], f2[N];
    int divs(int a, int b, int p)
    {
    	if (b % a == 0) return b / a;
    	int x = divs(p % a, a - b % a, a);
    	return (1ll * x * p + b) / a;
    }
    int C(int m, int n)
    {
    	if (n < 0 || m < 0 || n < m) return 0;
    	return 1ll * f1[n] * f2[m] % P * f2[n - m] % P;
    }
    int main()
    {
    	f1[0] = 1;
    	for (int i = 1; i <= Real_N; i++)
    		f1[i] = 1ll * f1[i - 1] * i % P;
    	f2[Real_N] = divs(f1[Real_N], 1, P);
    	for (int i = Real_N - 1; i >= 0; i--)
    		f2[i] = 1ll * f2[i + 1] * (i + 1) % P;
    	int T, a, b, c;
    	scanf("%d", &T);
    	while (T--)
    	{
    		scanf("%d %d", &a, &b);
    		c = a + a + b + b;
    		printf("%lld\n", (2ll * P + C(c / 2, c) - C(a - 1, c) - C(b - 1, c)) % P);
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    302
    时间
    1000ms
    内存
    512MiB
    难度
    7
    标签
    递交数
    2
    已通过
    1
    上传者