Wannafly Winter Camp 2020 Day 7F 草莓 - 构造

农场为一个 \(nm\) 的棋盘,初始位于第 \(x\) 行第 \(y\) 列,初始每个格子没草莓,每天早上每个格子长一个草莓,每天可以上下左右移动一次或不动,之后收获当前格子草莓,问 \(k\) 天后最多收多少草莓。

Solution

考虑答案的上界,假设我们一共走过了 \(x\) 个格子,答案的上界是这些格子最后剩下的草莓数量为 \(0,1,2...,x-1\)

不妨设 \(n \leq m\),显然在 \(n>1\) 时我们一定能达到上界

考虑 \(n=1\) 的情况,设 \(t=\min(x-1,n-x)\),即与左右边界的距离的较小值

如果 \(k\leq n-t\),即我们无法走到较远的那个边界,则答案为 \(1,2,3,...,k\)

如果 \(k\geq n+t\),即我们可以到最近的边界,再回头走过整个区域,则答案为 \(k,k-1,...,k-m\)

如果 \(n-t<k<n+t\),则我们可以先往比较宽阔的那边退几步,然后走回来,并恰好走到较近的那边,走到底,则答案为 \(\frac{k-(n-t)}{2}+1,...,k-1,k\)

构造题真是难受

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int mod = 998244353;
const int i2 = (mod+1)/2;

int solve(int l,int r) {
    l=max(l,0ll)%mod; r%=mod;
    return (l+r)*(r-l+1)%mod*i2%mod;
}

signed main() {
    int T,n,m,x,y,t,k;
    cin>>T;
    while(T--) {
        cin>>n>>m>>x>>y>>k;
        if(n>m) swap(n,m),swap(x,y);
        t=min(y-1,m-y);
        if(n==1 && m-t<k && k<m+t) cout<<solve((k-m+t)/2+1,k)<<endl;
        else cout<<solve(k-n*m+1,k)<<endl;
    }
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12378560.html