专栏文章
题解:AT_arc203_c
AT_arc203_c题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mioj1ar3
- 此快照首次捕获于
- 2025/12/02 20:00 3 个月前
- 此快照最后确认于
- 2025/12/02 20:00 3 个月前
ARC203C
注意到加粗的 ,分讨一下:
-
此时无法形成一条可行的路径,答案为 。
-
相当于往右下走的格路计数,方案数就是 。
-
相当于格路上随便加一条多余的边,记多余位置 ,方案数:
-
不难发现此时最短路径长度有 和 两种,分讨:
-
长度为先考虑随便加两条边,方案数是:但是这样会算重,考虑一个折角,即同时出现,那么分别考虑两个折角的时候就会算重。于是容斥掉这种折角,我们将两个折角看做从 的向右下的移动方式,这其实相当于把原来格路中的一个 和 替换成了一个 ,剩下 个 ,排列完再往里面插一个 ,容斥方案数就是
-
长度为我们令 为正方向,那么这种情况相当于在某个地方 ,然后某处再 ,或是在某个地方 ,然后某处再 ,为了方便我们可以只考虑往上走的情况,左同理。挖掘这个 放在什么位置才是合法的。发现,这个向上一定是 的情况,并且不能放在第一个 的前面和最后一个 的后面。考虑这样组合:放好 ,放 (同时保证其不在开头和结尾),放 。总共有 个 ,所以除掉开头结尾有 个位置,放 就有 种方案。然后再插 个 ,根据多重集的组合数有 种方案。因此对于上,总方案数就是对于左同理计算即可。
-
代码:
CPP#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int mod=998244353;
inline int Mod(int x) { return x<0 ? x+mod : (x>=mod ? x-mod : x); }
inline void adm(int &x,int y) { x=Mod(x+y); }
inline int qmi(ll a,int b)
{
ll res=1;
while (b)
{
if (b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
const int N=400000;
int fac[N+10],infac[N+10];
inline int binom(int a,int b)
{
if (a<0 || b<0 || a<b) return 0;
return (ll)fac[a]*infac[b]%mod*infac[a-b]%mod;
}
int main()
{
fac[0]=1;
for (int i=1;i<=N;i++) fac[i]=(ll)fac[i-1]*i%mod;
infac[N]=qmi(fac[N],mod-2);
for (int i=N-1;i>=0;i--) infac[i]=(ll)infac[i+1]*(i+1)%mod;
int T;
cin >> T;
while (T--)
{
int h,w,k;
cin >> h >> w >> k;
int t=(2ll*h*w-h-w-(h+w-2))%mod;
if (k<h+w-2) cout << "0\n";
else if (k==h+w-2) cout << binom(h+w-2,h-1) << "\n";
else if (k==h+w-1) cout << 1ll*binom(h+w-2,h-1)*t%mod << "\n";
else
{
int u=1ll*binom(h+w-2,h-1)*t%mod*Mod(t-1)%mod*infac[2]%mod;
int s=1ll*binom(h+w-4,h-2)*(h+w-3)%mod;
int up=1ll*(h-1)*binom(h+w-2,w-3)%mod;
int lft=1ll*(w-1)*binom(h+w-2,h-3)%mod;
int ans=((ll)Mod(u-s)+up+lft)%mod;
cout << ans << "\n";
}
}
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...