ABC240 G - Teleporting Takahashi
ABC240 G - Teleporting Takahashi 题解
题目简介
给出 和 ,求长度为 的三元组序列 满足:
输出方案数对 取模的结果。
URL = https://atcoder.jp/contests/abc240/tasks/abc240_g
Hint 1 : 2D
如果我们考虑下列一个简化问题,从 走到 ,总共走了 步,方案数为多少。
事实上,这个简化版本可以用 的时间复杂度计算。
轴走一步,相当于加上一个向量, 轴走一步,相当于加上一个向量。
如果考虑将坐标系从 映射到 ,那么上述四个步骤可以表示为加上向量:。
因此,将两个维度分别考虑即可,即对于 1D 维度,我们需要求解下列问题:
次操作,每次操作可以,问把 变成 的方案数为多少。
- 如果 是奇数,方案数为 。
- 如果 是偶数,方案数为 。
组合数公式为:,
对于,可以考虑预处理 的逆元(线性筛 + 前缀积),直接套公式计算。
Hint 2 : 枚举
考虑 3D 的问题,我们只需要枚举总共的 步,有 步是给 方向走的,那么剩余的 步就是在 这个平面内走的,这就化归到上述的 2D 情况。
对于一个确定的 ,首先要计算在 方向上走 步能否到达预定的数字,这也化归到上述的 1D 情况。此外由于一共进行了步,那么需要将先进行的步,分配到对应的位置,这些位置的个数为 。
由于组合数可以 计算,所以本题可以在 的时间复杂度内求解。
solution
时间复杂度:
空间复杂度:
# include <bits/stdc++.h>
# define int long long
using namespace std;
const int mo = 998244353;
const int N=1e7+10;
int s[N],t[N];
int c(int n,int m) {
int res;
if (n-m>=0 && n>=0 && m>=0) res = s[n]*t[m]%mo*t[n-m]%mo;
else res = 0;
return res;
}
int fun1(int n,int x) {
if ((n+x)%2 != 0) return 0;
return c(n,(n+x)/2);
}
int fun2(int n,int x,int y) {
return fun1(n,x+y)*fun1(n,x-y)%mo;
}
signed main() {
int n,x,y,z; cin>>n>>x>>y>>z;
s[0]=1; for (int i=1;i<=n;i++) s[i] = s[i-1]*i%mo;
t[1]=1; for (int i=2;i<=n;i++) t[i]=mo-mo/i*t[mo%i]%mo;
t[0]=1; for (int i=1;i<=n;i++) t[i]=t[i-1]*t[i]%mo;
int ans = 0;
for (int i=0;i<=n;i++) {
(ans += fun1(i,x) * c(n,i)%mo * fun2(n-i,y,z)%mo)%=mo;
}
cout<<ans<<endl;
return 0;
}