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(1≤n≤109) 个士兵攻击魔法师,这些士兵初始自由分为 m ( 1 ≤ m ≤ 1 0 7 ) m(1\le m\le 10^7) m(1≤m≤107) 组。
每一回合,每个存活的士兵会对魔法师造成 1 1 1 点伤害。之后魔法师选择一组士兵,击杀其中最多 k ( 1 ≤ k ≤ 1 0 7 ) k(1\le k\le 10^7) k(1≤k≤107) 人。
魔法师很聪明,总会采用最优策略。
如果士兵最终造成的最大总伤害不小于
x
(
1
≤
x
≤
1
0
13
)
x(1\le x\le 10^{13})
x(1≤x≤1013) ,则输出"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;
}