• bzoj千题计划168:bzoj3513: [MUTC2013]idiots


    http://www.lydsy.com/JudgeOnline/problem.php?id=3513

    组成三角形的条件:a+b>c

    其中,a<c,b<c

    若已知

    两条线段之和=i 的方案数g[i]

    线段长度>i的 线段数量 t[i]

    答案是否可以表示为 Σ g[i]*t[i] ?

    不能,因为 有c是最大的数的限制

    去掉c是最大数的限制:

    不能组成三角形的条件:a+b<=c

    其中,a<c,b<c

    在这里,满足条件的c一定是abc中最大的

    所以解题思路是 求出不能组成三角形的方案数S

    g[i] 两条线段和为i的方案数

    t[i] 线段长度>=i的 线段数

    f[i] 线段长度=i的线段数

    那么

    g的计算:

    g[i]= Σ f[j]*f[i-j]

    若 i是偶数 g[i]-=f[i/2]  (总长为i,方案数应该是f[i/2]*(f[i/2]-1),在式子中算的是f[i/2]*f[i/2])

    g[i]/=2 (每个方案被枚举了两次)

    S=Σg[i]*t[i]

    tot=C(n,3)

    ans=(tot-S)/ tot

    用fft 把g的计算优化到 nlogn

    多项式:g[]=f[]*f[]

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    const int N=1<<18;
    
    const double pi=acos(-1);
    
    struct Complex
    {
        double x,y;
        Complex() { }
        Complex(double x_,double y_) : x(x_),y(y_) {  }
        Complex operator + (Complex P)
        {
            Complex C;
            C.x=x+P.x;
            C.y=y+P.y;
            return C;
        }
        Complex operator - (Complex P)
        {
            Complex C;
            C.x=x-P.x;
            C.y=y-P.y;
            return C;
        }
        Complex operator * (Complex P)
        {
            Complex C;
            C.x=x*P.x-y*P.y;
            C.y=x*P.y+y*P.x;
            return C;
        }
    };
    
    typedef Complex E;
    
    E f[N];
    
    long long t[N],g[N];
    
    int n;
    
    int r[N];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void fft(E *a,int tag)
    {
        for(int i=0;i<n;++i)
            if(i<r[i]) swap(a[i],a[r[i]]);
        for(int i=1;i<n;i<<=1)
        {
            E wn(cos(pi/i),tag*sin(pi/i));
            for(int p=i<<1,j=0;j<n;j+=p)
            {
                E w(1,0);
                for(int k=0;k<i;++k,w=w*wn)
                {
                    E x=a[j+k],y=w*a[j+k+i];
                    a[j+k]=x+y; a[j+k+i]=x-y;
                }
            }
        }
    }
    
    int main()
    {
        int T;
        read(T);
        int a,mx;
        long long ans,tot;
        while(T--)
        {
            memset(t,0,sizeof(t));
            memset(g,0,sizeof(g));
            memset(f,0,sizeof(f));
            read(n);
            tot=(long long)n*(n-1)*(n-2)/6;
            mx=0;
            for(int i=1;i<=n;++i)
            {
                read(a);
                t[a]++;
                f[a].x++;
                g[a<<1]--;
                mx=max(mx,a);
            }
            for(int i=mx-1;i;--i) t[i]+=t[i+1]; 
            int m=mx-1<<1;
            int bit=0;
            for(n=1;n<=m;n<<=1) bit++;
            for(int i=0;i<n;++i) r[i]=(r[i>>1]>>1)|((i&1)<<bit-1);
            fft(f,1);
            for(int i=0;i<n;++i) f[i]=f[i]*f[i];
            fft(f,-1);
            for(int i=0;i<n;++i) g[i]+=(int)(f[i].x/n+0.5);
            ans=0;
            for(int i=0;i<n;++i) ans+=(g[i]>>1)*t[i];
            ans=tot-ans;
            printf("%.7lf
    ",ans*1.0/tot);
        }
    }

    3513: [MUTC2013]idiots

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 613  Solved: 219
    [Submit][Status][Discuss]

    Description

    给定n个长度分别为a_i的木棒,问随机选择3个木棒能够拼成三角形的概率。

    Input

    第一行T(T<=100),表示数据组数。
    接下来若干行描述T组数据,每组数据第一行是n,接下来一行有n个数表示a_i。
    3≤N≤10^5,1≤a_i≤10^5

    Output

    T行,每行一个整数,四舍五入保留7位小数。

    Sample Input

    2
    4
    1 3 3 4
    4
    2 3 3 4

    Sample Output

    0.5000000
    1.0000000

    HINT

    T<=20


    N<=100000

     

  • 相关阅读:
    eclipse+myeclipse 使用技巧备忘
    程序员的自我修养
    枚举工具类 EnumUtils
    日期/时间处理工具 DateTimeUtil
    轻松了解Spring中的控制反转和依赖注入(一)
    了解SpringMVC框架及基本工作流程
    HTTP请求行、请求头、请求体详解
    Tomcat项目部署问题记录
    入手IntelliJ IDEA 常用配置
    解决阿里云OSS跨域问题
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8156655.html
Copyright © 2020-2023  润新知