CodeForces-1657D For Gamers. By Gamers.
For Gamers. By Gamers.#
给出初始金币数
给出n个兵种,每个兵种有三个属性:分别代表购买一只该兵种的代价,伤害,血量
同时给出m个敌人,每个敌人有两个属性分别代表该敌人伤害,血量
每一次只面对一个敌人,同时刷新金币数(金币数回复初始值),并要求,每次面对敌人时,在任何一个兵不伤亡的情况下,战胜敌人所需要花费的最少金币数,如果金币数不够,则输出-1
同时给出购买兵种的约束,仅能买一种兵
二分
首先进行简单的分析:在什么情况下能战胜敌人
以给出的条件来看:
化简:
因此,就得到了只需要对比乘积的大小就可以知道是否能打过
接下来我们思考代价的问题,不难想出,这个代价是单调的,同时观察题目的数据范围——1e6,可以用数组储存,因此我们考虑使用二分,提前预处理所有的代价的最大乘积,然后直接二分寻找最小的代价
的意义是:花费代价i,所能得到的最大乘积是x
同时状态转移为:
对于所有的,都应该更新其i倍数的dp最大值,同时为了维护单调(取消离散化),状态还要从中转移
预处理完之后,直接二分就好了
时间复杂度,预处理类似埃氏筛,为nlogn级别
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 1e6 + 10;
const ll inf = 1e17 + 10;
ll dp[maxn];
int main()
{
int n, len;
scanf("%d%d", &n, &len);
for(int i=0; i<n; i++)
{
ll a, b, c;
scanf("%lld%lld%lld", &a, &b, &c);
// dp[a] = b * c;
dp[a] = max(dp[a], b * c);
}
for(ll i=1; i<=len; i++)
{
dp[i] = max(dp[i], dp[i-1]);
for(ll cur=2,j=i+i; j<=len; j+=i,cur++)
dp[j] = max(dp[j], dp[i]*cur);
}
int m;
scanf("%d", &m);
for(int i=0; i<m; i++)
{
ll a, b;
scanf("%lld%lld", &a, &b);
ll tot = a * b;
tot++;
if(tot > dp[len]) printf("-1 ");
else
{
int way = lower_bound(dp, dp + len + 1, tot) - dp;
printf("%d ", way);
}
}
printf("\n");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人