[HDU 7086]Pty plays game
题目大意
玩家有 个士兵, 有 个士兵,两边的士兵站成一个队列。
游戏过程如下:
-
两边队头的士兵相互攻击,当一名士兵阵亡时,他所在队列的下一个士兵会替补登场,若 的士兵全部阵亡而玩家的士兵还活着,玩家胜利。
-
每个士兵有 的生命值,单位时间内能对敌造成的伤害为 。
开战之前,可以选择 天的训练时间,每训练一天,士兵 的生命值与攻击力会增长 与 。
问是否 使得玩家胜利,若存在,输出最小的 ,否则,输出 。
分析
首先,对于这道题目,我们很容易向二分的方向去想,但我们并不知道其是否具有单调性,同时,我们不能在短时间内判断一个局面合法与否,考虑一次解决这些问题。
判断局面胜败
首先,我们注意到,如果玩家和 都只有一个士兵,分别为 , 则玩家打死 的士兵所用的时间 ,同理, 打死玩家的士兵所用的时间为 。
当 即 时,玩家将取得胜利。
考虑扩展这个局面,给 增加一个士兵为 ,而战胜 第一个士兵后,玩家的士兵状态变为 。
重复上面的过程,式子展开后我们发现玩家想要获胜需要 。
那么一般的,若一个局面满足:
则玩家获胜。
化简求值
那么,对于一个合法的 ,满足
发现可以把两边展开,化为一个二次函数 ,求满足条件的最小 。
于是我们可以展开分类讨论,进行求解。
-
当 时二次函数需要用到二分查找(当然也可以直接求根公式,
如果你能把精度卡过的话)。 -
当 时一次函数可以直接求根,注意如果是小数应该向哪边取整。
-
当 且 时,函数值不变,直接看 即可。
注:注意精度
CODE
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w*=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
struct node{
int x,y,dx,dy;
}a[N],b[N];
int T;
signed main()
{
// freopen("data1.in","r",stdin);
// freopen("data.out","w",stdout);
T=read();
while(T--){
int n=read(),m=read();
for(register int i=1;i<=n;i++){
a[i].x=read(),a[i].dx=read();
a[i].y=read(),a[i].dy=read();
}
for(register int i=1;i<=m;i++){
b[i].x=read(),b[i].dx=read();
b[i].y=read(),b[i].dy=read();
}
int A=0,B=0,C=0;
for(register int i=1;i<=n;i++){
A=A+a[i].dx*a[i].dy;
B=B+a[i].y*a[i].dx+a[i].x*a[i].dy;
C=C+a[i].x*a[i].y;
}
for(register int i=1;i<=m;i++){
A=A-b[i].dx*b[i].dy;
B=B-b[i].y*b[i].dx-b[i].x*b[i].dy;
C=C-b[i].x*b[i].y;
}
if(!A&&!B){
if(C>0) puts("0");
else puts("none");
continue;
}
if(!A){
int ans=(-C)/B;
if(B>0){
ans++;
if(C>0) puts("0");
else if(C==0) puts("1");
else printf("%lld\n",ans);
}
else{
if(C>0) puts("0");
else puts("none");
}
}
else{
if(A>0){
if(C>0) puts("0");
else{
long double l=0,r=1e18;
int ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(A*(long double)mid*(long double)mid+B*(long double)mid+C>0) ans=mid,r=mid-1;
else l=mid+1;
}
if(ans==-1) puts("none");
else printf("%lld\n",ans);
}
}
else{
if(C>0) puts("0");
else{
double p=-(double)B/(double)(2*A);
if(p<0) puts("none"); //对称轴小于0
else{
double mx=(double)A*p*p+(double)B*p+C;
//if(mx<0) { puts("none");
double l=0,r=(int)p+1;
int ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(A*(double)mid*(double)mid+B*(double)mid+C>0) ans=mid,r=mid-1;
else l=mid+1;
}
if(ans==-1) puts("none");
else printf("%lld\n",ans);
}
}
}
}
}
return 0;
}
本文作者:╰⋛⋋⊱๑落叶๑⊰⋌⋚╯
本文链接:https://www.cnblogs.com/Defoliation-ldlh/p/15413515.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步