zoukankan      html  css  js  c++  java
  • HDU

    题意:给你一堆线段的长度,求任选三条能组成三角形的概率。

    解法:先求出任选两条能组成的所有长度及其数量,这个过程可以用FFT实现。设a[i]代表长度为i的线段的数量,数组b为数组a的平方,然后从b中减去每条线段自己的贡献,即b[i*2]-=a[i],然后对所有的b[i]除以2,则b[i]就代表取两条线段长度和为i的方法数,剩下的用概率+前缀和搞一搞就行了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 typedef double db;
     5 const int N=4e5+10;
     6 const db pi=acos(-1);
     7 struct P {
     8     db x,y;
     9     P operator+(const P& b) {return {x+b.x,y+b.y};}
    10     P operator-(const P& b) {return {x-b.x,y-b.y};}
    11     P operator*(const P& b) {return {x*b.x-y*b.y,x*b.y+y*b.x};}
    12     P operator/(db b) {return {x/b,y/b};}
    13 } p[N];
    14 void FFT(P* a,int n,int f) {
    15     for(int i=1,j=n>>1,k; i<n-1; ++i,j^=k) {
    16         if(i<j)swap(a[i],a[j]);
    17         for(k=n>>1; j&k; j^=k,k>>=1);
    18     }
    19     for(int k=1; k<n; k<<=1) {
    20         P wn= {cos(pi/k),f*sin(pi/k)};
    21         for(int i=0; i<n; i+=k<<1) {
    22             P w= {1,0};
    23             for(int j=i; j<i+k; ++j,w=w*wn) {
    24                 P x=a[j],y=w*a[j+k];
    25                 a[j]=x+y,a[j+k]=x-y;
    26             }
    27         }
    28     }
    29     if(!~f)for(int i=0; i<n; ++i)a[i]=a[i]/n;
    30 }
    31 int n,m,mx;
    32 ll a[N],b[N];
    33 
    34 int main() {
    35     int T;
    36     for(scanf("%d",&T); T--;) {
    37         ll ans=0;
    38         memset(a,0,sizeof a),mx=0;
    39         scanf("%d",&n);
    40         for(int i=0; i<n; ++i) {
    41             int x;
    42             scanf("%d",&x);
    43             a[x]++;
    44             mx=max(mx,x);
    45         }
    46         memset(p,0,sizeof p);
    47         for(m=1; m<=2*mx; m<<=1);
    48         for(int i=0; i<m; ++i)p[i]= {a[i],0};
    49         FFT(p,m,1);
    50         for(int i=0; i<m; ++i)p[i]=p[i]*p[i];
    51         FFT(p,m,-1);
    52         for(int i=0; i<m; ++i)b[i]=p[i].x+0.5;
    53         for(int i=0; i<m; ++i)b[i*2]-=a[i];
    54         for(int i=0; i<m; ++i)b[i]/=2;
    55         for(int i=m-1; i>=0; --i)a[i]+=a[i+1];
    56         for(int i=0; i<m; ++i)ans+=a[i]*b[i];
    57         printf("%.7f
    ",1-ans*1.0/n/(n-1)/(n-2)*6);
    58     }
    59     return 0;
    60 }
  • 相关阅读:
    链表问题(5)-----读取
    链表问题(4)----环形链
    服务器上安装anaconda
    链表问题(3)-----反转
    (1)安装vagrant和virtualbox
    链表问题(2)-----删除
    链表问题(1)----遍历和实现
    Python笔记26----正则表达式匹配
    读书笔记--SQL必知必会04--过滤数据
    Docker
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10502745.html
Copyright © 2011-2022 走看看