#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long LL;
const int maxn=200005*2;
const double eps=0.000000000001;
const double PI=acos(-1.0);
struct Point
{
double x,y;
Point(double cx=0,double cy=0)
{
x=cx; y=cy;
}
};
struct Circle{
Point c;
double r;
Circle(Point c,double r):c(c),r(r){}
Point point(double a)
{
return Point(c.x+cos(a)*r,c.y+sin(a)*r);
}
};
int dcmp(double a)
{
if(fabs(a)<eps)return 0;
return a<0?-1:1;
}
double angle(Point v)
{
return atan2(v.y,v.x);
}
Point operator -(Point A, Point B)
{
return Point(A.x-B.x,A.y-B.y);
}
double Length(Point c)
{
return sqrt(c.x*c.x+c.y*c.y);
}
Point Rotate(Point A, double rad)
{
return Point(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
void getTangents(Point p, Circle C,double &A, double &B)
{
Point u=p;
double dist=Length(u);
if(dcmp(dist-C.r)==0){
double a=atan2(p.y,p.x);
if(a<0){
B=A=a+PI*2;
}else A=B=a;
}else{
double ang=acos(C.r/dist);
Point t=Rotate(u,ang);
double a=atan2(t.y,t.x);
if(a<0)
{
A=a+PI*2;
B=a-ang*2+PI*2;
}else{
A=a;
B=a-ang*2;
if(B<0)B+=PI*2;
}
}
}
Point P[maxn];
struct Elem
{
double L,R;
int cL,cR;
bool operator <(const Elem &rhs)const
{
return cL<rhs.cL||(cL==rhs.cL&&cR<rhs.cR);
}
}E[maxn];
double JJ[maxn*2];
int C[maxn*2];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int v,int n)
{
if(x<=0)return ;
while(x<=n)
{
C[x]+=v;
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=0;
while(x>0)
{
ans+=C[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
int n;
double d;
while(scanf("%d%lf",&n,&d)==2)
{
LL ge=0,nu=0,cc=0;
Circle c(Point(0,0),d);
for(int j=0; j<n; j++)
{
scanf("%lf%lf",&P[nu].x,&P[nu].y);
if(dcmp(Length(P[nu])-d)<0)
{
ge++;
}
else
{
getTangents(P[nu],c,E[nu].L,E[nu].R);
if(E[nu].L>E[nu].R)swap(E[nu].L,E[nu].R);
JJ[cc++]=E[nu].L;JJ[cc++]=E[nu].R;
nu++;
}
}
sort(JJ,JJ+cc);
ge=1;
for(int i=1; i<cc; i++)
{
if(dcmp(JJ[i]-JJ[ge-1])>0)JJ[ge++]=JJ[i];
}
cc=ge;
for(int i=0; i<=cc; i++)C[i]=0;
for(int i=0; i<nu; i++)
{
E[i].cL=upper_bound(JJ,JJ+cc,E[i].L)-JJ;
E[i].cR=upper_bound(JJ,JJ+cc,E[i].R)-JJ;
add(E[i].cL,1,cc);
add(E[i].cR,-1,cc);
}
sort(E,E+nu);
LL buhefa=0;
for(int i=0; i<nu; i++)
{
LL d1= sum(E[i].cR);
LL d2= sum(E[i].cL-1);
buhefa+=d1-d2;
add(E[i].cL,-1,cc);
add(E[i].cR,1,cc);
}
LL nn=n;
LL ans=nn*(nn-1)/2-buhefa;
printf("%lld\n",ans);
}
return 0;
}
/*
4 10
0 2
2 0
0 100
100 0
*/
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· Vite CVE-2025-30208 安全漏洞
· 《HelloGitHub》第 108 期
· MQ 如何保证数据一致性?
· 一个基于 .NET 开源免费的异地组网和内网穿透工具
2014-11-05 uva1025 dp