Description
给定一个等边三角形,三个顶点分别为 ((-L/2,0),(L/2,0),(0,sqrt 3L/2))
一束光线从 ((x,y)) 射出,速度为 ((v_x,v_y)),遇到墙壁会反射,保证不会射到顶点上
问第 (k) 次碰撞的时间
Solution
二分答案,考虑求在已知时间内的碰撞次数
把三角形边看成是镜子,问题就转化为在无限密铺等边三角形中的运动
考虑与 (x) 轴平行的线,这样答案为 (|lfloor frac y {frac {sqrt 3}{2} L} floor|)
然后通过绕中心旋转 (2pi /3) 使得斜边成为平边,然后重复上述过程即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
const double pi = acos(-1);
const double a = 120*pi/180;
const double d = sqrt(3)/6;
double l;
int k;
struct point
{
double x,y;
point operator + (const point &b)
{
return {x+b.x, y+b.y};
}
point operator * (double k)
{
return {k*x,k*y};
}
} r,v;
point rotate(point p,double a)
{
point res;
res.x = p.x*cos(a) - p.y*sin(a);
res.y = p.x*sin(a) + p.y*cos(a);
return res;
}
point calc(point p)
{
p.y -= d*l;
p = rotate(p,a);
p.y += d*l;
return p;
}
int eval(point p)
{
return abs(floor(2*p.y/sqrt(3)/l));
}
int check(double tim)
{
int ans=0;
point t=r+v*tim;
ans+=eval(t);
t=calc(t);
ans+=eval(t);
t=calc(t);
ans+=eval(t);
return ans;
}
void solve()
{
cin>>l>>r.x>>r.y>>v.x>>v.y>>k;
double l=0,r=1e9;
while(r-l>1e-6)
{
double mid=(l+r)/2;
//cout<<"mid="<<mid<<" chk="<<check(mid)<<endl;
if(check(mid)>=k) r=mid;
else l=mid;
}
cout<<setiosflags(ios::fixed)<<setprecision(8)<<l<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
solve();
}
}