DYOJ 【20220317模拟赛】瞬间移动 题解

瞬间移动

题意

三维空间中从 \((0,0,0)\) 开始,每次移动 1,问刚好走 \(N\) 次能到 \((X,Y,Z)\) 的方案数

\(N\le10^7\),答案模 \(998244353\)

Sol

一个感觉很简单的题,结果。。。

不失一般性地,设 \(x,y,z\ge0\)

显然当 \(x+y+z>n\)\((n-x-y-z)\mod2=1\) 时答案为 0

先只考虑前两维,设 \(F_k\) 为从 \((0,0)\) 一共走 \(X+Y+2k\) 步到 \((X,Y)\) 的方案数

\[\begin{aligned} F_k &= \sum_{i=0}^k \begin{pmatrix} x+y+2k \\ x+i\quad i\quad y+k-i\quad k-i \end{pmatrix} \\ &= \sum_{i=0}^k \begin{pmatrix} x+y+2k \\ x+y+k \end{pmatrix} \begin{pmatrix} x+y+k \\ y+k-i \end{pmatrix}\begin{pmatrix} k \\ i \end{pmatrix} \\ &= \begin{pmatrix} x+y+2k \\ x+y+k \end{pmatrix}\sum_{i=0}^k \begin{pmatrix} x+y+k \\ y+k-i \end{pmatrix}\begin{pmatrix} k \\ i \end{pmatrix} \\ &= \begin{pmatrix} x+y+2k \\ x+y+k \end{pmatrix} \begin{pmatrix} x+y+2k \\ y+k \end{pmatrix} \end{aligned} \]

解释

首先:

\[\begin{pmatrix} n\\ a\quad b\quad c \quad d \end{pmatrix} = \begin{pmatrix} n\\a \end{pmatrix}\begin{pmatrix} n-a\\b \end{pmatrix} \begin{pmatrix} n-a-b\\c \end{pmatrix}\begin{pmatrix} n-a-b-c\\d \end{pmatrix} \]

先后顺序可以交换


其次:

\[\begin{pmatrix} n \\ m \end{pmatrix}\begin{pmatrix} n-m \\ r \end{pmatrix} = \begin{pmatrix} n \\ m+r \end{pmatrix}\begin{pmatrix} m+r \\ r \end{pmatrix} = \begin{pmatrix} n \\ m+r \end{pmatrix}\begin{pmatrix} m+r \\ m \end{pmatrix} \]

\(n\) 个里面分别选出 \(m,r\) 个的方案数

等同于

先从 \(n\) 里面选出 \(m+r\) 个,其中再选出 \(m\)\(r\) 个的方案


  1. 第一个式子可以化成 \(\begin{pmatrix} x+y+2k \\ x+i\quad y+k-i\end{pmatrix}\begin{pmatrix} k \\ i\quad k-i \end{pmatrix}\)

    前面那一部分化成 \(\begin{pmatrix} x+y+2k \\ x+y+k \end{pmatrix} \begin{pmatrix} x+y+k \\ y+k-i \end{pmatrix}\)

    后面化成 \(\begin{pmatrix} k \\ i \end{pmatrix}\) ,可得第二个式子。

  2. 第二个式子提出与 \(i\) 无关项得到第三个式子

  3. 第三个式子的 \(\sum_{i=0}^k \begin{pmatrix} x+y+k \\ y+k-i \end{pmatrix}\begin{pmatrix} k \\ i \end{pmatrix}\)

    其实就是从 \(x+y+2k\) 个球中选 \(y+k\) 个,枚举最后 \(k\) 个中选了多少个

    \(\begin{pmatrix} x+y+2k \\ y+k \end{pmatrix}\)

到三维

直接枚举 \(z\) 走的步数即可,复杂度 \(O(n)\)

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL P = 998244353;
const int N = 1e7 + 5;
inline LL Pow(LL x, LL y) {
    register LL res = 1;
    for (; y; y >>= 1, x = x * x % P)
        if (y & 1) res = res * x % P;
    return res;
}
LL fac[N], inv[N], res;
inline LL C(int n, int m) {
    if (m > n) return 0;
    return fac[n] * inv[m] % P * inv[n - m] % P;
}
int n, X, Y, Z, le, tt;
inline LL count(int k) {
    return C(X + Y + 2 * k, X + Y + k) * C(X + Y + 2 * k, Y + k) % P;
}
int main() {
    // freopen("teleport.in", "r", stdin);
    // freopen("teleport.out", "w", stdout);
    scanf("%d%d%d%d", &n, &X, &Y, &Z);
    X = abs(X), Y = abs(Y), Z = abs(Z), le = X + Y + Z, fac[0] = 1;
    if (n < le) return puts("0"), 0;
    if ((n - le) & 1) return puts("0"), 0;

    for (int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % P;
    inv[n] = Pow(fac[n], P - 2);
    for (int i = n - 1; ~i; i--) inv[i] = inv[i + 1] * (i + 1) % P;
    tt = (n - le) / 2;
    for (int z = 0; z <= tt; z++)
        (res += C(n, z) * C(n - z, Z + z) % P * count(tt - z) % P) %= P;
    printf("%lld", res);
}

总结

这个式子就是经典的范德蒙德卷积。

高级的名字,本质是组合数的变换

以后遇到这种题要记得各种性质,大胆去推

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值