2025牛客寒假训练营6 J题题解

2025牛客寒假训练营6 J题题解

题目链接:https://ac.nowcoder.com/acm/contest/95338/J
解题思路:分为以下四种情况:
1.如果 y ≥ n y\geq n yn,那么显然每回合都要磨刀,从某个回合开始连续杀怪,直到游戏结束。设 t t t为从第一个回合开始连续不杀怪的回合,设 D ( t ) D(t) D(t)为在前述条件下造成的总伤害值,可以得出 D ( 0 ) = n ( x + 1 ) D(0)=n(x+1) D(0)=n(x+1)。然后由特殊推一般,可得 D ( t ) = ( n − t ) ( x + 1 − t ) D(t)=(n-t)(x+1-t) D(t)=(nt)(x+1t)。令 ∂ D ∂ t = 0 \frac{\partial D}{\partial t}=0 tD=0可得, t = n − ( x + 1 ) 2 = t 0 t=\frac{n-(x+1)}{2}=t_0 t=2n(x+1)=t0。此时再分为以下两种情况:
1)如果 n ≤ x + 1 n\leq x+1 nx+1,那么显然当 t = 0 t=0 t=0 D ( t ) D(t) D(t)取得最大值 D ( 0 ) D(0) D(0)
2)否则,当 t = t 0 t=t_0 t=t0时取得最大值,最大值为 ( n + x + 1 ) 2 4 \frac{(n+x+1)^2}{4} 4(n+x+1)2。但这里要注意一点,如果 n % 2 ≠ ( x + 1 ) % 2 n\%2\neq(x+1)\%2 n%2=(x+1)%2,那么最大值为 D ( t 0 ) − 1 4 D(t_0)-\frac{1}{4} D(t0)41
综上所述, D max ⁡ = { n ( x + 1 ) n ≤ x + 1 ⌊ ( n + x + 1 ) 2 4 ⌋ n > x + 1 D_{\max}=\begin{cases} n(x+1)&n\leq x+1 \\ \lfloor\frac{(n+x+1)^2}{4}\rfloor & n>x+1\end{cases} Dmax={n(x+1)4(n+x+1)2nx+1n>x+1
2.如果 x + 2 y − 1 ≤ n x+2y-1\leq n x+2y1n,那么最优解就是先把刀磨到最亮(攻击力为 x + y x+y x+y),然后从用完最后一个磨刀石的回合开始杀怪,直到把刀用坏。此时造成的总伤害值就是 ( x + y ) ( x + y + 1 ) 2 \frac{(x+y)(x+y+1)}{2} 2(x+y)(x+y+1)
3.如果 x + 2 y − 1 > n x+2y-1>n x+2y1>n,这时就要看从哪个回合开始杀怪可以造成最大伤害值。容易证明,最优解肯定在前y次的范围内。设 t t t为从第一个回合开始连续不杀怪的回合,设 D ( t ) D(t) D(t)为在前述条件下造成的总伤害值。显然,用完最后一个磨刀石的那一个回合结束后时,刀的攻击力为 x + t x+t x+t,如果 x + t ≤ n − y x+t\leq n-y x+tny,那么游戏还没结束,刀就被用坏了,此时 D ( t ) = ( x + 1 + t ) ( y − t ) + ( x + t ) ( x + t + 1 ) 2 D(t)=(x+1+t)(y-t)+\frac{(x+t)(x+t+1)}{2} D(t)=(x+1+t)(yt)+2(x+t)(x+t+1);否则,这把刀足够用剩下的 ( n − y ) (n-y) (ny)个回合,此时 D ( t ) = ( x + 1 + t ) ( y − t ) + ( n − y ) ( ( x + t ) + ( x + t + 1 − ( n − y ) ) 2 D(t)=(x+1+t)(y-t)+\frac{(n-y)((x+t)+(x+t+1-(n-y))}{2} D(t)=(x+1+t)(yt)+2(ny)((x+t)+(x+t+1(ny)),此时答案为 min ⁡ t ∈ [ 0 , n ] D ( t ) \min_{t\in[0,n]}D(t) mint[0,n]D(t)。这种情况似乎没办法用一个多元初等函数来表示,只能跑暴力寻找解。好在 O ( T y ) \mathcal O(Ty) O(Ty)的时间复杂度可以通过本题。

#include<iostream>
#include<iomanip>
#include<cstring>
#include<numeric>
#include<cmath>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<climits>
#include<array>
#include<queue>
#include<bitset>

#define int long long
#define cd(n,d) std::cout<<std::fixed<<std::setprecision((n))<<(d) 
#define ms(a,b) std::memset((a),(b),sizeof(a))
#define mc(a,b) std::memcpy((a),(b),sizeof(b))
#define all(v) (v).begin(),(v).end()
#define _all(v,n) (v),(v)+(n)
#define sum(v,x) std::accumulate((v).begin(),(v).end(),(x))
#define _sum(v,n,x) std::accumulate((v),(v)+(n),(x))
#define fill(v,x) std::fill((v).begin(),(v).end(),(x))
#define iota(v,x) std::iota((v).begin(),(v).end(),(x))
#define _fill(v,n,x) std::fill((v),(v)+(n),(x))
#define _iota(v,n,x) std::iota((v),(v)+(n),(x))
#define cln std::cout<<"\n"
#define eb emplace_back
#define pb pop_back
#define ef emplace_front
#define pf pop_front 
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define FOR0(i,x,y) for(int i=(x);i<(y);i++)
#define _FOR(i,x,y) for(int i=(x);i>=(y);i--)
#define _FOR0(i,x,y) for(int i=(x);i>(y);i--)
#define F first
#define S second

using PII=std::pair<int,int>;

void solve(){
	int n,x,y;
	std::cin>>n>>x>>y;
	if(y>=n){
		if(n<=x+1){
			std::cout<<n*(x+1)<<"\n";
		}else{
			std::cout<<(n+1+x)*(n+1+x)/4<<"\n";
		}
	}else{
		if(x+2*y-1<=n){
			std::cout<<(x+y)*(x+y+1)/2<<"\n";
		}else{
			int ans=0;
			FOR(t,0,y){
				int damage;
				if(x+y+t>n){
					damage=(x+1+t)*(y-t)+(n-y)*((x+1+t-1)+(x+1+t-(n-y)))/2;
				}else{
					damage=(x+1+t)*(y-t)+(x+t)*(x+1+t)/2;
				}
				ans=std::max(ans,damage);
			}
			std::cout<<ans<<"\n";
		}
	}
}

signed main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	
	int T=1;
	std::cin>>T;
	
	while(T--){
		solve();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值