“蔚来杯“2022牛客暑期多校训练营5 I题: Board Game

I题: Board Game

原题链接:https://ac.nowcoder.com/acm/contest/33190/I

题目大意

n ( 1 ≤ n ≤ 1 0 9 ) n(1\le n\le 10^9) n(1n109) 个士兵攻击魔法师,这些士兵初始自由分为 m ( 1 ≤ m ≤ 1 0 7 ) m(1\le m\le 10^7) m(1m107) 组。

每一回合,每个存活的士兵会对魔法师造成 1 1 1 点伤害。之后魔法师选择一组士兵,击杀其中最多 k ( 1 ≤ k ≤ 1 0 7 ) k(1\le k\le 10^7) k(1k107) 人。

魔法师很聪明,总会采用最优策略。
如果士兵最终造成的最大总伤害不小于 x ( 1 ≤ x ≤ 1 0 13 ) x(1\le x\le 10^{13}) x(1x1013) ,则输出"YES"和可能造成的最大伤害,否则输出"NO"。

题解

当人数较小时,多次尝试可以发现均分是最好的策略。
对于魔法师而言,一个 x + k x+k x+k 的组等价于两个分别为 x , k x,k x,k 的组,因此我们的策略是将人划分为若干个 k k k 组,剩下的均分为 m m m 组(每组中不超过 k k k 人,否则可以继续分出)。
枚举均分组中的总人数即可。
最终的人数应该有三种, k k k 人,均分上取整人数,均分下取整人数,魔法师肯定从人数多的开始杀,分为三段等差数列求和计算伤害即可。

参考代码

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

template<class T>inline void read(T&x){
	char c,last=' ';
	while(!isdigit(c=getchar()))last=c;
	x=c^48;
	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+(c^48);
	if(last=='-')x=-x;
}

#define ll long long
ll n,m,k,x;
ll ans;

void cal(ll x){//x表示k人的组数
	ll rest=n-x*k;//剩下的均分人数
	ll y=rest%m,z=m-y,d=rest/m,sum=0;//y为上取整人数,z为下取整人数
	sum+=(n+(n-x*k+k))*x/2;//最多人组的为k人
	sum+=((n-x*k)+(n-x*k-y*(d+1)+d+1))*y/2;//最多人的组为均分上取整
	sum+=((z*d)+(d))*z/2;//最多人的组为均分下取整
	ans=max(ans,sum);
}

int main()
{
	read(n),read(m),read(k),read(x);
	for(ll r=n%k,p=n%k;p<=n&&p<=r+m*k;p+=k){//r表示余数,均分部分的人数一定是r+ak的形式,枚举至r+mk即可(这时均分中上取整人数其实已经超过了m)
		cal((n-p)/k);
	}
	if(ans>=x)cout<<"YES "<<ans<<'\n';
	else puts("NO");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值