zoukankan      html  css  js  c++  java
  • 【STSRM13】木之本樱

    【题意】抽象模型后转化为:给定n个直线,ans+=C(x,4)*8,x为每个经过直线数>=4的点的直线数,不存在平行直线。

    【算法】数学

    【题解】

    运用了一个很简单的道理:经过同一个点的线段互相相交。

    O(n^3),枚举直线i和j相交,然后枚举后面直线判断是否过交点的条数x,将C(x,2)累加入答案。

    O(n^2*log n),只要O(n^2)跑一边交点(不去重),排序,统计相同交点有几个就可以得知经过该交点的直线数了。

    访问x次,则可由1+2+3+...+n-1=x求得n。

    注意多关键字double排序。

    注意eps=1e-6足矣。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int read()
    {
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    /*------------------------------------------------------------*/
    const int inf=0x3f3f3f3f,maxn=810,maxN=640100;
    const double eps=1e-6;
    struct cyc{double x,y;}anss[maxN];
    int n,x1[maxn],x2[maxn],y1_[maxn],y2[maxn],tot;
    double k[maxn],b[maxn];
    ll c[maxn],d[maxN];
    void insert(double x,double y){anss[++tot].x=x;anss[tot].y=y;}
    bool cmp(cyc a,cyc b){return fabs(a.x-b.x)>eps?a.x<b.x:a.y<b.y;}
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            x1[i]=read(),y1_[i]=read(),x2[i]=read(),y2[i]=read();
            if(x2[i]-x1[i])k[i]=1.0*(y2[i]-y1_[i])/(x2[i]-x1[i]);
            b[i]=1.0*y1_[i]-k[i]*x1[i];
        }
        tot=0;
        for(int i=1;i<n;i++){
            for(int j=i+1;j<=n;j++){
                if(x2[i]-x1[i]==0){
                    if(x2[j]-x1[j]==0)continue;
                    insert(x1[i],k[j]*x1[i]+b[j]);
                }else if(x2[j]-x1[j]==0){
                    insert(x1[j],k[i]*x1[j]+b[i]);
                }else{
                    double X=(b[i]-b[j])/(k[j]-k[i]);
                    double Y=k[i]*X+b[i];
                    insert(X,Y);
                }
            }
        }
        sort(anss+1,anss+tot+1,cmp);
        c[4]=1;
        for(int i=5;i<=n;i++)c[i]=c[i-1]*i/(i-4);
        ll number=3;
        for(int i=4;i<=n;i++){number+=i-1;d[number]=i;}
        ll ans=0,num=0;
        anss[0].x=anss[0].y=-1;
        for(int i=1;i<=tot;i++)if(fabs(anss[i].x-anss[i-1].x)<eps&&fabs(anss[i].y-anss[i-1].y)<eps)num++;else{
            ans+=c[d[num]];num=1;
        }
        ans+=c[d[num]];
        printf("%lld",ans*8);
        return 0;
    }
    View Code
  • 相关阅读:
    二维数组最大子数组算法
    寻找最大子数组
    最大值bug 调试
    多路电梯调度算法
    分析一个文本文件各个词出现的频率,并把频率最高的十个词打印出来。
    使用redis实现生产者消费者模式
    简单使用redis实现sso单点登录
    MongoDB批量导入及简单的性能优化
    mysql安装
    字符串操作性能优化
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7346770.html
Copyright © 2011-2022 走看看