CFP559C Gerald and Giant Chess 学习笔记
CFP559C Gerald and Giant Chess 学习笔记
前言
观察数据范围,不难猜测解法是 \(k^2\) 的。
有人可能会问了,啊我一眼看到这题觉得这只能 \(2^k\) 做怎么办呢?
小编也很惊讶,然而解法确实是 \(k^2\) 的。
所以场上 ICPC-2025-I WHN 的 G,唐唐不会!令人忍俊不禁。
题意简述
给定 \(n\times m\) 的网格,其中有 \(k\) 个黑格。
问从 \((1,1)\) 开始,每步只能往右或往下移动一格,不经过黑格到达 \((n,m)\) 的方案数。
\(n,m\le 10^5,k\le 2\times 10^3\)。
做法解析
首先如果一个黑格都没有,答案显然是 \(\dbinom{n+m-2}{n-1}\)。但是有黑格,而且这个数据范围不接受 \(2^k\) 容斥,你只能 \(k^2\) 干掉。
我们要是能确保把每个黑格的某种贡献算得不重不漏,最后一并用总方案数减掉就好了。那么什么时候会算重呢?
我们设 \(dp_{i}\) 为从起点到终点且只经过第 \(i\) 黑格的路径数,我们发现这玩意不好不重不漏;于是退而求其次,设 \(dp_{i}\) 为从起点到第 \(i\) 黑格格,途中不经过其它黑格的路径数,我们发现这玩意能去重了!为什么?因为“黑格 \(j\) 能拦在从起点到黑格 \(i\)”这一影响关系出现当且仅当 \(x_j\le x_i,y_j\le y_i\),这种关系最终可以形成一个DAG。
具体来说,我们有转移式子:\(dp_i=\dbinom{x_i+y_i-2}{x_i-1}\sum_{j}dp_j\times \dbinom{x_i-x_j+y_i-y_j}{x_i-x_j}[x_j\le x_i,y_j\le y_i]\)。
然后我们把终点也当成一个黑格考虑,把这个式子套进去就得到答案了!
代码实现
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
using namespace omodint;
using mint=m107;
const int MaxN=1e5+5,MaxK=2e3+5;
mint facr[MaxN*2],finv[MaxN*2],dp[MaxK];
using namespace omathe;
int N,M,K,X,Y;
struct anob{
int x,y;
friend bool operator<(anob a,anob b){return a.x==b.x?a.y<b.y:a.x<b.x;}
}A[MaxK];
int main(){
readis(N,M,K),premwork(N+M);
for(int i=1;i<=K;i++)readis(X,Y),A[i]={X,Y};
A[K+1]={N,M},sort(A+1,A+K+2);
for(int i=1;i<=K+1;i++){
auto [xi,yi]=A[i];
dp[i]=Comb(xi+yi-2,xi-1);
for(int j=1;j<i;j++){
if(A[j].y>A[i].y)continue;auto [xj,yj]=A[j];
dp[i]-=dp[j]*Comb((xi-xj)+(yi-yj),(xi-xj));
}
}
writi(miti(dp[K+1]));
return 0;
}
浙公网安备 33010602011771号