P9552 「CROI · R1」浣熊的小溪

去洛谷看我的博客

本题看似很难,实际上只需要找找规律就好。

先从样例入手。

样例给的例子是只有两行的特殊情况,我们可以先从这个特殊情况入手。

我们发现,当一条线向下穿过的时候,设与中间的线交点为 P。那么如果 P 不在格点上时,下一行就会从这列开始,如果 P 在格点上,那么就会从下一列开始。显然,前一种会比后一种多一个格子,所以只有前种策略最优。

再把问题的范围扩大到一般情况,有了上面的结论,我们可以发现,如果总格子是 n × m n\times m n×m。那么最优解一定是 n + m − 1 n+m-1 n+m1,证明如下。

首先这条线可以水平切,那么就是 n n n 个格子,然后我们再固定一端,把另一端向下移动。当这条线穿过了两行时,如果与中间的线的交点不在格点上,那么就会多出一个格子。再继续向下移动,直到穿过了 m m m 行,这时一共交了 m − 1 m-1 m1 条水平线,最多多产生 m − 1 m-1 m1 个格子被穿过。

综上所述,当总格子是 n × m n\times m n×m 时,最多可穿过 n + m − 1 n+m-1 n+m1 个格子。

于是,第一个问题就很容易地解决了。

再看看第二个问题,如果想要穿过的格子数大于等于 Q Q Q,也就代表 n ′ + m ′ − 1 n'+m'-1 n+m1 最小也要等于 Q Q Q。也就是说我们知道了 n ′ + m ′ n'+m' n+m 想要求满足 n ′ ≤ n , m ′ ≤ m n'\leq n,m'\leq m nn,mm 的情况下,使得 n ′ × m ′ n'\times m' n×m 最小。

小学数学老师告诉我们,矩形周长一定时,长宽差距越小,面积越大。所以, n ′ n' n 或者 m ′ m' m 某一个尽可能的小就可以让 n ′ × m ′ n'\times m' n×m 尽可能的大。显然,如果 n > m n>m n>m ,就让 m ′ = m , n ′ = Q + 1 − m m'=m,n'=Q+1-m m=m,n=Q+1m,反之同理。

因为无论是 n ′ = n n'=n n=n 还是 m ′ = m m'=m m=m,对应的 m ′ − m m'-m mm n ′ − n n'-n nn 的值都是 Q + 1 − n − m Q+1-n-m Q+1nm。所以第二问的答案就是 min ⁡ ( n , m ) × ( Q + 1 − n − m ) \min(n,m)\times(Q+1-n-m) min(n,m)×(Q+1nm)

AC 代码

#include<bits/stdc++.h>
using namespace std;
const unsigned long long mod=998244353;//因为数据比较大,所以我直接开的unsigned long long
unsigned long long n,m,k,d;
int T;
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%llu%llu%llu",&k,&n,&m);
		if(k==1) printf("%llu\n",n+m-1);
		else scanf("%llu",&d),d=d+1-n-m,d%=mod,printf("%llu\n",min(n,m)%mod*d%mod);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值