GYM102978A Ascending Matrix 题解
LGV引理的题目。
我们考虑这道题目是从\((1,1)\)到\((n,m)\),然后选取不交叉的\(k-1\)条线插在中间,每一条划分出一个数值的范围,题目限制相当于\((r,c)\)坐下方要有\(v-1\)条线。
我们考虑把线实际化成为一个点,不交叉变为点不相交,可以使用LGV引理。\((r,c)\)位移到了\((r+v-1,c+v-1)\),确保一下这一个点不会被选。
对于\(v-1\)条的限制,我们可以给\((r+v-1,c+v-1)\)左下方的若干条线段的权值从\(1\)改为\(x\),直接计算肯定是会爆炸的,但是根据拉格朗日插值的写法,我们可以给\(x\)带入\(k\)个值,运用LGV引理,就可以求出来方案数了。
2025.4.30补充:注意,带入\(x\)是往左下角,而不是下方,因为没来一条线都会位移。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int modd=998244353;
int a[310][310],K,n,m,jie[1010],ni[1010],zhi,x[1010],y[1010],r,c,v;
int g[1010],lin[1010],f[1010],jvch[310][310],jvxi[310][310],t[1010];
int kuai(int q,int w){
zhi=1;
while(w){
if(w&1){
zhi=zhi*q%modd;
}
q=q*q%modd;
w=w>>1;
}
return zhi;
}
inline int Guass(){
int ans=1;
for(int i=1;i<=K;i++){
if(!a[i][i]){
for(int j=i+1;j<=K;j++){
if(a[j][i]){
swap(a[i],a[j]);
ans=modd-ans;
break;
}
}
}
ans=ans*a[i][i]%modd;
int inv=kuai(a[i][i],modd-2);
for(int j=i+1;j<=K;j++){
int tmp=a[j][i]*inv%modd;
for(int k=i;k<=K;k++){
a[j][k]=(a[j][k]-tmp*a[i][k]%modd+modd)%modd;
}
}
}
return ans;
}
int C(int q,int w){
return jie[q]*ni[w]%modd*ni[q-w]%modd;
}
int calc(int sx,int sy,int ex,int ey){
if(ex>sx||ey<sy){
return 0;
}
return C(sx-ex+ey-sy,ey-sy);
}
void solve(){
for(int i=1;i<=K+1;i++){
t[i]=1;
for(int j=1;j<=K+1;j++){
if(i!=j){
t[i]=t[i]*(x[i]-x[j])%modd;
}
}
t[i]=(t[i]+modd)%modd;
t[i]=y[i]*kuai(t[i],modd-2)%modd;
}
lin[0]=1;
for(int i=1;i<=K+1;i++){
for(int j=K;j>0;j--){
lin[j]=(lin[j-1]+lin[j]*(modd-x[i])%modd)%modd;
}
lin[0]=lin[0]*(modd-x[i])%modd;
}
for(int i=1;i<=K+1;i++){
int inv=kuai(modd-x[i],modd-2);
g[0]=lin[0]*inv%modd;
for(int j=1;j<=K;j++){
g[j]=(lin[j]-g[j-1]+modd)*inv%modd;
}
for(int j=0;j<=K;j++){
f[j]=(f[j]+t[i]*g[j]%modd+modd)%modd;
}
}
return;
}
signed main(){
jie[0]=1,ni[0]=1;
for(int i=1;i<=1000;i++){
jie[i]=jie[i-1]*i%modd;
ni[i]=kuai(jie[i],modd-2);
}
cin>>n>>m>>K>>r>>c>>v;
r+=v-2;
c+=v-2;
K--;
for(int i=0;i<K;i++){
for(int j=0;j<K;j++){
jvch[i][j]=(calc(n+i,i,j,m+j)-calc(n+i,i,r,c)*calc(r,c,j,m+j)%modd+modd)%modd;
for(int d=1;d<=r&&d<=c;d++){
int xx=r-d,yy=c-d;
int res=calc(n+i,i,xx,yy)*calc(xx,yy,j,m+j)%modd;
jvxi[i][j]=(jvxi[i][j]+res)%modd;
jvch[i][j]=(jvch[i][j]-res+modd)%modd;
}
}
}
for(int i=1;i<=K+1;i++){
memset(a,0,sizeof(a));
x[i]=i;
for(int j=0;j<K;j++){
for(int k=0;k<K;k++){
a[j+1][k+1]=(jvch[j][k]+jvxi[j][k]*i)%modd;
}
}
y[i]=Guass();
}
solve();
cout<<f[v-1];
return 0;
}
浙公网安备 33010602011771号