[AGC040F] Two Pieces 题解
Solution
这个题真的挺难的。/kk 看了一个下午的题解才搞懂。/fn
我们发现我们如果设状态 表示前面的一个点在 ,另一个在 ,那么三种操作相当于:
-
都
-
-
很显然 操作 是为了不在 的时候与 算重。另外一个可以观察到的性质就是 操作会操作 次。
那么我们先考虑没有三操作的情况。可以发现相当于从 ,每次要么右上要么向下,且不能碰到 轴的方案数,这个可以用翻折法算出时 。
考虑有三操作的情况,假设我们使用 操作 次,那么 操作就会使用 次。我们发现如果抽出所有的 操作,那么显然是合法的,并且最后会在 处,而我们需要到达 。注意到我们设第 次操作后纵坐标为 ,那么我们在 之后加入一个 操作就需要满足当 时 ,因为我们相当于把 及其以后的 都减去 。这就可以看出同一权值的 如果后面有加入 操作的,那么一定是最后一个位置。另外一个性质是假设在集合 之后加入了 操作,那么最后纵坐标会减少 。
有了上面两个性质,那么我们就可以看出我们最后一次 操作前面一次的 一定是 ,而我们在 每个 权值后面都可以在最后一个位置后面加入一次 操作。那么贡献即是:。
那么我们就可以 解决这个问题了。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define mod 998244353
#define MAXN 20000005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
int n,A,B,fac[MAXN],ifac[MAXN];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
return res;
}
void Add (int &a,int b){a = add (a,b);}
void Sub (int &a,int b){a = dec (a,b);}
int binom (int a,int b){return a >= b ? mul (fac[a],mul (ifac[b],ifac[a - b])) : 0;}
signed main(){
read (n,A,B);int up = 2e7;
fac[0] = 1;for (Int i = 1;i <= up;++ i) fac[i] = mul (fac[i - 1],i);
ifac[up] = qkpow (fac[up],mod - 2);for (Int i = up;i;-- i) ifac[i - 1] = mul (ifac[i],i);
int ans = 0;
for (Int k = 0;k <= A && k <= n - B;++ k){
int v = B == 0 ? 1 : dec (binom (B + k - 1,k),binom (B + k - 1,B));
if (k == A) Add (ans,v);
else Add (ans,mul (v,binom (n - B - k - 1 + A - k,A - k)));
}
write (ans),putchar ('\n');
return 0;
}
分类:
思维题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通