dtoj4697. 格
dtoj4697. 格
有一个 $n$ 行 $m$ 列的矩阵,初始所有位置的权值都为 $0$.
开始时,你在格子 $(x,y)$ 上。
每天早上,每个格子里的权值都会增加 $1$.
每天下午,你可以留在当前格子,或瞬移到上下左右相邻格子中的一个。
每天晚上,你会获得当前格子里的权值,然后清空当前格。
求第 $k$ 天晚上后,你所获权值的最大值。
Sol
先考虑n>1,m>1
1如果k<nm 那么直接走就可以。
2如果矩阵有曼哈顿回路,那么就一直走曼哈顿回路。
3否则先等着,到还剩nm天时把矩阵走满。
然后考虑n=1的情况。记起点到短的那一边长度Mi
先考虑1
如果可以k>=MI+m 那就先走到一边然后3
否则先向短的那边走(m-Mi-1)步,然后往另一边
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define ll long long #define mod 998244353 using namespace std; ll T,n,m,x,y,k,n2=499122177,ans; ll S(ll l,ll r){ l%=mod,r%=mod; return ((l+r)%mod)*((r-l+1)%mod)%mod*n2%mod; } void work(){ scanf("%lld%lld%lld%lld%lld",&n,&m,&x,&y,&k); if(n>m)swap(n,m),swap(x,y); if(n==1){ ll Mi=min(y,m-y+1),Mx=max(y,m-y+1); if(k<=Mx)ans=S(1,k); else if(k>=m+Mi)ans=S(k-m+1,k); else { ll d=(k+Mi-m+1)/2; ans=S(d,k); } } else ans=S(max(k-n*m+1,0LL),k); ans=(ans%mod+mod)%mod; printf("%lld\n",ans); } int main(){ for(scanf("%lld",&T);T--;work()); return 0; }