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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/liankewei/p/12382530.html
今日推荐