题目描述
众所周知,9406计算机大佬众多,他们不仅代码能力强,而且都精通物理。物理无处不在,甚至坐电梯的时候,zck和xxr都在讨论若电梯突然失重会怎样。身为文科生的华华和奕奕非常难过,他们决定学习物理,不能让小伙伴们看不起。奕奕现在正在研究一道物理题。
有Q次操作:
若op<mark>1,输入v,t,m,表示在t时刻从无穷高处以初速度v垂直向下抛出一个质量为m的小球。
若op</mark>2,输入v,t。表示询问t时刻所有速度小于等于v的小球的动能之和是多少。
一个速度为v,质量为m的物体的动能等于0.5mvv,为了防止精度误差,设原来的答案是ans,则你只需输出2ans%(1e9+7)即可。
输入描述:
输入Q。 接下来Q行。
先输入op,若op<mark>1,输入v,t,m。
若op</mark>2,输入v,t表示一次询问。
1<=Q,t,m<=3e5。
若op<mark>1,1<=v<=3e5。
若op</mark>2,1<=v<=4e6。
t是不严格递增的,即t[1]<=t[2]<=t[3]<=…<=t[Q]
重力加速度取g=10m/s^2
输出描述:
对于每次询问输出2*ans%(1e9+7)
示例1
输入
复制
7
1 1 1 2
2 1 2
2 11 2
1 3 2 5
1 1 4 3
2 20 4
2 30 4
输出
复制
0
242
3
2648
如果我们不做改变,很难判断有哪些速度是小于当前询问的速度的。
于是我们想到,我们定一个标准。全部都看成从 t = 0 时开始丢下的小球,那么我们就很好判断了,直接树状数组维护一下即可。
那我们怎么计算答案呢?我们可以看一下公式: m * (v0 + g * t) ^2
,不难化简,我们维护三个变量即可,因为起点已经确定了,所以最后把t带入计算答案即可。
AC代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int p=1e9+7;
const int N=8e6+10,base=4e6;
int q,d[N][3];
inline void add(int x,int v,int k){for(;x<=base*2;x+=(x&(-x))) d[x][k]+=v;}
inline int ask(int x,int k){int s=0; for(;x;x-=(x&(-x))) s+=d[x][k]; return s;}
signed main(){
cin>>q;
while(q--){
static int op,v,t,m; scanf("%lld %lld %lld",&op,&v,&t);
if(op==1){
scanf("%lld",&m); v-=10*t;
add(v+base,m*v%p*v%p,0);
add(v+base,100*m,1);
add(v+base,(20*v*m%p+p)%p,2);
}else{
v-=10*t; static int res=0;
res=ask(v+base,0);
res=(res+ask(v+base,1)*t%p*t%p)%p;
res=(res+ask(v+base,2)*t%p)%p;
printf("%lld\n",res);
}
}
return 0;
}