zoukankan      html  css  js  c++  java
  • 【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根木棍不能构成三角形:最长边大于等于其余两边之和。

    因为长度只有$10^5$,因此可以直接记录由两根木棒拼成某长度的方案数,然后直接求前缀和统计答案即可。

    但是朴素的统计方案数的时间复杂度是$O(n^2)$的,会TLE。

    考虑到两边的长度s2[]和一边的长度s1[]的卷积有关,因此可以先使用FFT求某长度的个数s1[]的卷积,然后由于两根相同的木棒统计到了答案中,需要减掉;其余的方案出现了2次,需要再除以2.

    最后求前缀和统计答案即可。注意需要long long。

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 100010
    using namespace std;
    typedef long long ll;
    const int len = 262144;
    const double pi = acos(-1);
    struct data
    {
    	double x , y;
    	data() {}
    	data(double x0 , double y0) {x = x0 , y = y0;}
    	data operator+(const data &a)const {return data(x + a.x , y + a.y);}
    	data operator-(const data &a)const {return data(x - a.x , y - a.y);}
    	data operator*(const data &a)const {return data(x * a.x - y * a.y , x * a.y + y * a.x);}
    }a[N << 2];
    int w[N];
    ll sum[N << 2];
    void fft(int flag)
    {
    	int i , j , k;
    	for(i = k = 0 ; i < len ; i ++ )
    	{
    		if(i > k) swap(a[i] , a[k]);
    		for(j = len >> 1 ; (k ^= j) < j ; j >>= 1);
    	}
    	for(k = 2 ; k <= len ; k <<= 1)
    	{
    		data wn(cos(2 * pi * flag / k) , sin(2 * pi * flag / k));
    		for(i = 0 ; i < len ; i += k)
    		{
    			data w(1 , 0) , t;
    			for(j = i ; j < i + (k >> 1) ; j ++ , w = w * wn)
    				t = w * a[j + (k >> 1)] , a[j + (k >> 1)] = a[j] - t , a[j] = a[j] + t;
    		}
    	}
    }
    void work()
    {
    	int i;
    	fft(1);
    	for(i = 0 ; i < len ; i ++ ) a[i] = a[i] * a[i];
    	fft(-1);
    	for(i = 0 ; i < len ; i ++ ) a[i].x /= len;
    }
    int main()
    {
    	int T;
    	scanf("%d" , &T);
    	while(T -- )
    	{
    		memset(a , 0 , sizeof(a));
    		int n , i;
    		ll ans = 0;
    		scanf("%d" , &n);
    		for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &w[i]) , a[w[i]].x ++ ;
    		work();
    		for(i = 1 ; i <= n ; i ++ ) a[w[i] * 2].x -- ;
    		for(i = 1 ; i < len ; i ++ ) sum[i] = sum[i - 1] + (ll)(a[i].x / 2 + 0.1);
    		for(i = 1 ; i <= n ; i ++ ) ans += sum[w[i]];
    		printf("%.7Lf
    " , 1 - (long double)ans / ((long double)n * (n - 1) * (n - 2) / 6));
    	}
    	return 0;
    }
    
  • 相关阅读:
    vue less使用/(除号/斜杠),浏览器不识别问题
    antDesignOfVue 表格复选框添加了默认选中状态,点击清空后数据清空,复选框的选中状态不变的问题。
    vue 可多选的日期插件
    antDesignOfVue 走马灯组件不自动定位到第一页
    antDesignOfVue 表格固定列之后出现空白列
    vue 动态添加表格列
    antDesignOfVue 符合条件的表格复选框禁止选中
    更换文件名大小写之后,git远程文件还存在,删除远程仓库的文件/文件夹
    git文件名大小写不敏感,更改文件大小写后无反应。
    记:mysql查询列含中文
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7366911.html
Copyright © 2011-2022 走看看