CSP模拟赛T1 手机(awesome)
手机(awesome)
【题目描述】
三星 galaxy fold 终于发布了,作为全球第一个拿到这部手机的第三方,自如决定独享
这个 moment。手机刚刚开售,他就购买了首批所有手机,然后,他就等着快递员将手机送
货上门。自如的家和快递仓库都位于一条直线上。我们将自如的家定为零点,将这条直线看
作一条数轴,则每一个仓库都在数轴上的整点上。每一个仓库都有一个快递员同时出发,开
车前往自如的家。每个快递员开车的速度并不一样,而到自如家的路只允许并排行驶一辆车,
则当一个快递员发现前面有一辆慢车的时候,他就只能减速,紧跟那辆慢车行驶(不考虑车
身长度)。现在自如想知道,对于从每一个仓库送来的手机,将会在什么时间到达自如的手
中?
【输入】
第一行一个整数 n,表示仓库的数量
接下来 n 行,每行两个整数𝑝 𝑖 ,𝑤 𝑖 ,表示 i 号仓库的位置和从 i 号仓库出发的快递员的车
速。
【输出】
N 行,每行一个整数,表示从 i 号仓库送出的手机到达自如家的时间。
由于时间可能不是整数,输出其对 1000000007 取模的值。
【样例输入】
3
1 1
2 1
3 2
【样例输出】
1
2
2
【数据范围】
对于 30%的数据,n<=30
对于 100%的数据,n<=100000,\(\left\vert pi\right\vert \\\),𝑤𝑖 ≤ \(10^9\)
【提示】
对于分数 p/q,其对 m 取模的方式为找到一个整数 r,使得 q×r≡1(mod m),取模结果即
为 p×r (mod m)。
理解
一看这道题,就想打个大模拟,但仔细思考一下,可以很容易发现,如果一个人可以追上他前面的人,那么他们就会一起到终点!!!(划重点)
解题过程?
1.正方向和负方向分开考虑...(话说如果不这么做的话难道还把放到一起跑)
2.二者实际是一个问题,只考虑正方向(把负的变成正的在处理就行)
3.按照编号从小到大枚举每一个仓库,并且计算手机从仓库出发不考虑前方慢车到自如手中的时间。
4.考虑之前枚举到的仓库最晚到达自如手中的时间为b,刚才计算到的值为a,则当前仓库的手机到达自如手中的真实时间则为max(a,b)。(因为咱要减速)
5.时间复杂度O(n)(散花✿✿ヽ(°▽°)ノ✿)
参考代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5,mod=1e9+7;
int n;
int ans[N];
struct node {
int p,v,id;
} t[N],g[N];
inline bool cmp(node x,node y) {
return x.p<y.p;
}
inline int ksm(int x,int y) {
int ans=1;
while(y) {
if(y&1) {
ans=(1LL*ans*x)%mod;
}
x=(1LL*x*x)%mod;
y>>=1;
}
return ans;
}
signed main() {
scanf("%lld",&n);
int e=0,b=0;
for(int i=1; i<=n; ++i) {
int p,v;
scanf("%lld%lld",&p,&v);
if(p>=0) {
t[++e]=(node) {
p,v,i
};
} else {
g[++b]=(node) {
-p,v,i
};
}
}
sort(t+1,t+e+1,kkk);
double maxe=0;
int res=0;
for(int i=1; i<=e; ++i) {
double now=double(t[i].p)/t[i].v;
if(now>maxe) {
maxe=now;
res=(1LL*t[i].p*ksm(t[i].v,mod-2));
}
ans[t[i].id]=res+mod;
}
maxe=0,res=0;
sort(g+1,g+b+1,kkk);
for(int i=1; i<=b; ++i) {
double now=double(g[i].p)/g[i].v;
if(now>maxe) {
maxe=now;
res=(1LL*g[i].p*ksm(g[i].v,mod-2));
}
ans[g[i].id]=res+mod;
}
for(int i=1; i<=n; ++i) {
printf("%lld\n",ans[i]%mod);
}
return 0;
}
-----若转载请附原作者名及原文链接-----