P8508 做不完的作业 验题人题解
我是验题人。我和出题人的两种贪心其实不大一样,然后有挺多人反应看不懂我的代码,原因是 5ab 把我的巨丑代码挂到题解上去了。
首先说一说贪心。我的贪心是:按顺序考虑每个任务,每个任务安排在其最早能放的那一天。
有人可能有疑惑:有可能第 天原本安排的其中一个任务 ,将其替换为睡觉,将任务 往后推,会不会更优。事实上是不会的:如果你把 推到了 天,那么你有可能会增多一天消耗,但是对于第 天及以后的天,你没有增加任何的前缀睡觉时间(因为做任务的总量恒定,睡觉量也恒定)。所以不可能减少一天。
然后怎么写这个贪心。直接模拟?很遗憾,被毒瘤的出题人卡掉了,你会 TLE 几个点。因为直接模拟你需要模拟每一天的情况,这样的复杂度和总天数相关。所以我们需要加一个小优化:对于一个任务,如果你需要先睡好几天才能完成它,那么计算出睡的天数,而不一天一天地模拟。
容易发现这样的复杂度是线性的。
在计算天数的时候,可能需要稍微推一下式子,接下来是一些简单的推导。
以下用 表示一天的总时间,与题面不同。假设当前面对的是第 个任务,需要 的时间,目前总睡觉时间是 ,现在是第 天。那么当 的时候,这一天内肯定完成不了任务。我们计算需要连续睡几天觉,假设要再睡 天,那么有 ,简单移项可得:,取最小的 即可。
稍微修缮了一下的代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1000005;
ll n,m,p,q;
ll a[N];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m >> p >> q;
for (int i=1;i<=n;i++) cin >> a[i];
ll tot=1,sl=0;
for (ll j=1;;j++)
{
if ((m-a[tot]+sl)*q<m*p*j)
{
ll i=(m*p*j-(m-a[tot]+sl)*q+(m*(q-p))-1)/(m*(q-p));
j+=i,sl+=i*m;
}
ll x=m;
while (1)
{
if (tot==n+1) break;
if (x<=a[tot]) break;
if ((x-a[tot]+sl)*q<m*p*j) break;
x-=a[tot],tot++;
}
sl+=x;
if (tot==n+1)
{
cout << j;
return 0;
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类