bzoj 3513: [MUTC2013]idiots -- FFT

3513: [MUTC2013]idiots

Time Limit: 20 Sec  Memory Limit: 128 MB

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

Source

好像只能手写complex。。\\好生气(︶︿︶)

不知道为什么我的常数巨大。。。

原谅我粘个题解qaq

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<complex>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
//#define cp complex<double>
#define inf 1000000007
#define ll long long
#define PI 3.1415926535897932384626433832795028841971693993751
#define N 400010
char xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
#define isd(c) (c>=‘0‘&&c<=‘9‘)
inline int rd(){
    char xchh;
    int xaa;
    while(xchh=getc(),!isd(xchh));(xaa=xchh-‘0‘);
    while(xchh=getc(),isd(xchh))xaa=xaa*10+xchh-‘0‘;return xaa;
}
struct cp{
     double r,i;
    cp(double _r=0,double _i=0):r(_r),i(_i){}
    cp operator + (cp x){return cp(r+x.r,i+x.i);}
    cp operator - (cp x){return cp(r-x.r,i-x.i);}
    cp operator * (cp x){return cp(r*x.r-i*x.i,r*x.i+i*x.r);}
    void clear(){r=i=0.0;}
};
cp a[N],b[N];
int r[N],m,L,M;
void fft(cp *x,int f)
{
    for(int i=0;i<m;i++) if(i<r[i]) swap(x[i],x[r[i]]);
    for(int i=1;i<m;i<<=1)
    {
        cp wn(cos(PI/i),f*sin(PI/i));
        for(int j=0;j<m;j+=(i<<1))
        {
            cp w(1,0),X,Y;
            for(int k=0;k<i;k++,w=w*wn)
            {
                X=x[j+k];Y=w*x[k+j+i];
                x[j+k]=X+Y;x[j+k+i]=X-Y;
            }
        }
    }
}
int T,n,c,p[N],f[N],mx;
ll ans,sum,tot;
int main()
{
    T=rd();
    register int i;
    while(T--)
    {
        n=rd();mx=0;
        memset(p,0,sizeof(p));
        for(i=1;i<=n;++i) c=rd(),p[c]++,mx=max(mx,c);
        M=(mx+1)<<1;for(m=1,L=-1;m<M;m<<=1) L++;
        for(i=0;i^m;++i) r[i]=(r[i>>1]>>1)|((i&1)<<L);
        for(i=0;i^m;++i) a[i].r=b[i].r=p[i],a[i].i=b[i].i=0;
        fft(a,1);fft(b,1);
        for(i=0;i^m;i++) a[i]=a[i]*b[i];
        fft(a,-1);
        sum=ans=0;tot=(ll)n*(n-1)*(n-2)/6;
        for(i=0;i<=mx;i++)
        {
            sum+=(ll)(a[i].r/m+0.5);
            if(!(i&1)) sum-=p[i>>1];
            if(!p[i]) continue;
            ans+=sum*p[i];
        }
        ans/=2;
        printf("%.7lf\n",1.0-ans*1.0/tot);
    }
    return 0;
}
时间: 2024-10-12 12:33:58

bzoj 3513: [MUTC2013]idiots -- FFT的相关文章

BZOJ 3513: [MUTC2013]idiots

Description 求一个序列能够成的三角形个数.\(n \leqslant 10^5,a_i \leqslant 10^5\) Sol FFT. 我们可以用FFT求出任意两个形成的组合,不过要减去重复的. 我先算的是排列,最后除6变成组合. 然后考虑将第三条边加入,这时候只需要减去所有小于等于这条边的长度的个数*3即可. 因为这样正确的原因是我假设的一个条件,假设的是我们选的这条边是最长边,这样减掉的边都会比他短,也就考虑了所有方案. 因为算的是排列,并且其他两个的顺序已经确定,有三个位置

【bzoj3513】[MUTC2013]idiots FFT

题目描述 给定n个长度分别为a_i的木棒,问随机选择3个木棒能够拼成三角形的概率. 输入 第一行T(T<=100),表示数据组数. 接下来若干行描述T组数据,每组数据第一行是n,接下来一行有n个数表示a_i. 3≤N≤10^5,1≤a_i≤10^5 输出 T行,每行一个整数,四舍五入保留7位小数. 样例输入 2 4 1 3 3 4 4 2 3 3 4 样例输出 0.5000000 1.0000000 题解 FFT 考虑什么样的3根木棍不能构成三角形:最长边大于等于其余两边之和. 因为长度只有$1

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中最大的 所以解题思路是 求出不能

bzoj 3160: 万径人踪灭 manachar + FFT

3160: 万径人踪灭 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 133  Solved: 80[Submit][Status][Discuss] Description Input Output Sample Input Sample Output HINT 以每一个位置为中心,分别处理连续一块的回文串,回文序列个数. 比较容易看出是FFT+manachar,但是FFT还是不太熟悉,特别要注意三层for语句中i,j,k不能写错,这东西很难调

【BZOJ 2179】【FFT模板】 FFT快速傅立叶

2179: FFT快速傅立叶 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 1595 Solved: 792 [Submit][Status][Discuss] Description 给出两个n位10进制整数x和y,你需要计算x*y. Input 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数为n的正整数y. Output 输出一行,即x*y的结果. Sample Input 1 3 4 Sample Output

BZOJ 3771 生成函数,FFT

Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: "这把斧头,是不是你的?" 樵夫一看:"是啊是啊!" 水神把斧头扔在一边,又拿起一个东西问: "这把斧头,是不是你的?" 樵夫看不清楚,但又怕真的是自己的斧头,只好又答:"是啊是啊!" 水神又把手上的东西扔在一边,拿起第三个东西问: "这把斧头,是不是你的?" 樵夫还是看不清楚,

BZOJ 3527: [Zjoi2014]力 FFT

3527: [Zjoi2014]力 Description 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. Input 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. n≤100000,0<qi<1000000000 Output n行,第i行输出Ei.与标准答案误差不超过1e-2即可. Sample Input 5 4006373.885184 15375036.435759 1717456.469144 8514941.004912 1410681.34

BZOJ 4827 [Hnoi2017]礼物 ——FFT

题目上要求一个循环卷积的最小值,直接破环成链然后FFT就可以了. 然后考虑计算的式子,可以分成两个部分分开计算. 前半部分FFT,后半部分扫一遍. #include <map> #include <ctime> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <alg

bzoj3513 [MUTC2013]idiots

Description 给定n个长度分别为a_i的木棒,问随机选择3个木棒能够拼成三角形的概率. Input 第一行T(T<=20),表示数据组数. 接下来若干行描述T组数据,每组数据第一行是n,接下来一行有n个数表示a_i.1<=a_i<=100000,N<=100000 Output T行,每行一个整数,四舍五入保留7位小数. 设a(x)表示长度x的木棒出现次数 b(x)表示选两根木棒(可重)长度之和为x的方案数 显然b(m)=Σ a(x)*a(m-x) x=0..m,可以用f