Codeforces Round #462 (Div. 1) :C,D

C:

平面图的欧拉定理,对于一个平面图,设其边数为 E E ,点数为V,连通块数目为 C C ,区域数为F,那么: F=EV+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+y2nk=Lnj=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+y2nk=Lnj=LkjL=x2+y2nk=Ln((k+12)(L2))L=x2+y2n((n+23)(L+13)(n+1L)(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 计算贡献即可。(拆开的y是一个前缀形式,可以 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值