C:
平面图的欧拉定理,对于一个平面图,设其边数为 E E ,点数为,连通块数目为 C C ,区域数为,那么: F=E−V+C+1 F = E − V + C + 1 恒成立。
对于此题直接求出所有交点,判重之后带入公式即可。
#include<bits/stdc++.h>
typedef long double LD;
using namespace std;
const LD eps=1e-6;
inline int sgn(LD x) {return (x>eps)-(x<-eps);}
int n,tot,vis[5],V,E,C;
vector <int> edge[5];
struct P {
LD x,y;
P(LD x=0,LD y=0):x(x),y(y){}
friend inline P operator +(const P &a,const P &b) {return P(a.x+b.x,a.y+b.y);}
friend inline P operator -(const P &a,const P &b) {return P(a.x-b.x,a.y-b.y);}
friend inline P operator *(const P &a,LD x) {return P(a.x*x,a.y*x);}
friend inline P operator /(const P &a,LD x) {return P(a.x/x,a.y/x);}
friend inline bool operator <(const P &a,const P &b) {
int t=sgn(a.x-b.x);
if(t!=0) return t<0;
return a.y<b.y;
}
friend inline bool operator ==(const P &a,const P &b) {
return (!sgn(a.x-b.x))&&(!sgn(a.y-b.y));
}
inline P e() {
LD len=sqrt(this->dis());
return P(x/len,y/len);
}
inline LD dis() {return x*x+y*y;}
inline P rev(LD ang) {return P(x*cos(ang)-y*sin(ang),x*sin(ang)+y*cos(ang));}
}st[233];
struct Cir {
P a;
LD R;
}cir[5];
const LD PI=acos(-1.0);
inline void calc(int a,int b) {
if(cir[a].R<cir[b].R) swap(a,b);
LD dis=(cir[b].a-cir[a].a).dis();
LD R1=cir[a].R-cir[b].R, R2=cir[a].R+cir[b].R;
if(sgn(R2*R2-dis)>=0 && sgn(R1*R1-dis)<=0) {
edge[a].push_back(b);
edge[b].push_back(a);
LD cs=(cir[a].R*cir[a].R+dis-cir[b].R*cir[b].R)/2.0/cir[a].R/sqrt(dis);
cs=acos(cs);
P o=(cir[b].a-cir[a].a).e()*cir[a].R;
st[++tot]=o.rev(cs)+cir[a].a;
st[++tot]=o.rev(2*PI-cs)+cir[a].a;
}
}
inline void dfs(int x) {
vis[x]=1;
for(int e=edge[x].size()-1;e>=0;e--) {
int v=edge[x][e];
if(!vis[v]) dfs(v);
}
}
inline bool on(const P &a,const Cir &b) {
LD dis=(b.a-a).dis();
return !sgn(dis-b.R*b.R);
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {cin>>cir[i].a.x>>cir[i].a.y>>cir[i].R;}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
calc(i,j);
sort(st+1,st+tot+1); tot=unique(st+1,st+tot+1)-st-1;
V=tot;
for(int i=1;i<=n;i++) if(!vis[i]) ++C,dfs(i);
for(int i=1;i<=n;i++)
for(int j=1;j<=tot;j++)
if(on(st[j],cir[i])) ++E;
printf("%d\n",E-V+C+1);
}
D:
这道题对于我来说比赛的时候是不可能打完的,因为细节太多了,但是思想还是很好懂的。
考虑直接枚举每个点计算贡献,那么:
ans=∑L=x2+y2n∑k=Ln∑j=Lkj
a
n
s
=
∑
L
=
x
2
+
y
2
n
∑
k
=
L
n
∑
j
=
L
k
j
有公式:
∑i=LR(ix)=(R+1x+1)−(Lx) ∑ i = L R ( i x ) = ( R + 1 x + 1 ) − ( L x )
原文没写怎么证,其实也挺好证的,因为 (ix)=(i+1x+1)−(i+1x) ( i x ) = ( i + 1 x + 1 ) − ( i + 1 x ) 。
然后就特别 Naive N a i v e 了,有:
ans===∑L=x2+y2n∑k=Ln∑j=Lkj∑L=x2+y2n∑k=Ln((k+12)−(L2))∑L=x2+y2n((n+23)−(L+13)−(n+1−L)(L2))
a
n
s
=
∑
L
=
x
2
+
y
2
n
∑
k
=
L
n
∑
j
=
L
k
j
=
∑
L
=
x
2
+
y
2
n
∑
k
=
L
n
(
(
k
+
1
2
)
−
(
L
2
)
)
=
∑
L
=
x
2
+
y
2
n
(
(
n
+
2
3
)
−
(
L
+
1
3
)
−
(
n
+
1
−
L
)
(
L
2
)
)
然后拆开组合数,暴力枚举 x x 计算贡献即可。(拆开的是一个前缀形式,可以 O(1) O ( 1 ) 计算贡献)。
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
const LL mod=1e9+7;
const LL inv2=(mod+1)/2,inv3=(mod+1)/3,inv5=(mod*2+1)/5,inv6=inv2*inv3%mod,inv7=(mod+1)/7;
LL n,ans;
inline LL mul(LL x,LL y) {return (x%mod)*(y%mod)%mod;}
inline void add(LL &x,LL y) {x=(x+y>=mod?x+y-mod:x+y);}
inline void dec(LL &x,LL y) {x=(x-y<0)?x-y+mod:x-y;}
inline LL power(LL x,LL t) {
if(t==1) return x%mod;
return mul(x,power(x,t-1));
}
inline LL sum2(LL x) {
return mul(x,mul(x+1,2*x+1))*inv6%mod;
}
inline LL sum4(LL x) {
return mul(x,mul(x+1,mul(2*x+1,3*mul(x,x)+3*x-1)))*inv5%mod*inv6%mod;
}
inline LL sum6(LL x) {
LL rs=0;
add(rs,x*inv6%mod*inv7%mod);
dec(rs,power(x,3)*inv6%mod);
add(rs,power(x,5)*inv2%mod);
add(rs,power(x,6)*inv2%mod);
add(rs,power(x,7)*inv7%mod);
return rs;
}
int main() {
cin>>n; LL cnt=0;
for(LL x=1;x*x<n;++x) {
LL y=sqrt(n-x*x); add(cnt,y);
add(ans, power(mul(x,x),3)*y%mod*2%mod);
add(ans, power(mul(x,x),2)*sum2(y)%mod*6%mod);
add(ans, power(mul(x,x),1)*sum4(y)%mod*6%mod);
add(ans, sum6(y)*2%mod);
dec(ans, power(mul(x,x),2)*y%mod*((3*n+6)%mod)%mod);
dec(ans, power(mul(x,x),1)*sum2(y)%mod*((3*n+6)%mod)%mod*2%mod);
dec(ans, sum4(y)*((3*n+6)%mod)%mod);
add(ans, power(mul(x,x),1)*y%mod*((3*n+4)%mod)%mod);
add(ans, sum2(y)*((3*n+4)%mod)%mod);
add(ans, mul(power(n,3),y));
add(ans, mul(power(n,2)*3,y));
add(ans, mul(n*2,y));
} ans=ans*4%mod; cnt=cnt*4%mod;
LL rs=0,cc=0;
for(LL x=1;x*x<=n;++x) {
add(ans, 8*power(mul(x,x),3)%mod);
dec(ans, mul(mul(3*n+6,power(mul(x,x),2)),4));
add(ans, mul(mul(3*n+4,mul(x,x)),4));
add(ans, 4*power(n,3)%mod);
add(ans, 4*power(n,2)*3%mod);
add(ans, 4*n*2%mod);
}
add(ans, power(n,3)%mod);
add(ans, power(n,2)*3%mod);
add(ans, n*2%mod);
ans=ans*inv6%mod;
cout<<ans<<endl;
}