[hdu4609]计数方法,FFT
题目:给一个数组a,从里面任选三个数,求以这三个数为三条边能构成三角形的概率。
思路:由于每个数只能用一次,所以考虑枚举三边中的最大边。先将a数组排序,然后枚举它的每个数x作为最大边,那么问题就是要求在数组a剩余的数里面“找小于等于x”且“和大于x”的数对个数,答案显然不能直接得到。不妨先计算这样一个数组ans[i]:表示在数组a里面有放回的选两个数,和为i的数对个数。设cnt[i]为i这个数在a数组里面出现的次数,那么ans相当于cnt对cnt的卷积结果, 这可以利用FFT在nlogn的时间内求得。ans数组出来以后,由于还需要将它变成“无放回地取两个数”的结果,且要保证答案的无序性(由于每个答案都会被统计两次,全部除以2即可),需要做些处理,具体见代码。处理完后,ans[i]表示从a数组里面任选两个数和为i的方案数,就可以利用ans来得到答案了。
先对ans进行前缀和处理(ans[i]+=ans[i-1]),在枚举到最大边x时,另两边的和可以为x+1~maxsum的任意值,将答案加上ans[maxsum] - ans[x]---(1),由于加的这个答案里面包含很多不合法的,需要一一减去,下面对不合法的进行分类{设共n个数,范围为[a,a+n),现在枚举到了i这个位置,数为x,需要注意的是由于已经排序,下面的大小关系是指位置的大小关系,而不用特别去考虑相等情况了}:
(1)两边都大于x,显然它们的和大于x,所以会出现在(1)里面,需要减去: (n-i-1)*(n-i-2)/2
(2)一边大于x,一边小于x,显然它们的和也大于x,会出现在(1)里面,需要减去:i*(n-i-1)
(3)一边等于x,一边不等于x,显然他们的和也大于x,会出现在(1)里面,需要减去:n-1
这样枚举完所有数,就得到答案了。
另外,整体看减去的数,是一个常数,而枚举每个数累加的ans值跟次序无关 ,于是根本无需排序,一样得到正确的结果。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
/* ******************************************************************************** */#include <iostream> //#include <cstdio> //#include <cmath> //#include <cstdlib> //#include <cstring> //#include <vector> //#include <ctime> //#include <deque> //#include <queue> //#include <algorithm> //#include <map> //#include <cmath> //using namespace std; // //#define pb push_back //#define mp make_pair //#define X first //#define Y second //#define all(a) (a).begin(), (a).end() //#define fillchar(a, x) memset(a, x, sizeof(a)) // //void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);} //void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R> //void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1; //while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T> //void print(const T t){cout<<t<<endl;}template<typename F,typename...R> //void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T> //void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;} // //typedef pair<int, int> pii; //typedef long long ll; //typedef unsigned long long ull; // //template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);} //template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);} //template<typename T> //void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];} //template<typename T> //void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];} // //const double PI = acos(-1); // ///* -------------------------------------------------------------------------------- */namespace FFT { const static int maxn = 1e5 + 7; #define L(x) (1 << (x)) double ax[maxn << 2], ay[maxn << 2], bx[maxn << 2], by[maxn << 2];//需要四倍空间 int revv(int x, int bits) { int ret = 0; for (int i = 0; i < bits; i++) { ret <<= 1; ret |= x & 1; x >>= 1; } return ret; } void fft(double * a, double * b, int n, bool rev) { int bits = 0; while (1 << bits < n) ++bits; for (int i = 0; i < n; i++) { int j = revv(i, bits); if (i < j) swap(a[i], a[j]), swap(b[i], b[j]); } for (int len = 2; len <= n; len <<= 1) { int half = len >> 1; double wmx = cos(2 * PI / len), wmy = sin(2 * PI / len); if (rev) wmy = -wmy; for (int i = 0; i < n; i += len) { double wx = 1, wy = 0; for (int j = 0; j < half; j++) { double cx = a[i + j], cy = b[i + j]; double dx = a[i + j + half], dy = b[i + j + half]; double ex = dx * wx - dy * wy, ey = dx * wy + dy * wx; a[i + j] = cx + ex, b[i + j] = cy + ey; a[i + j + half] = cx - ex, b[i + j + half] = cy - ey; double wnx = wx * wmx - wy * wmy, wny = wx * wmy + wy * wmx; wx = wnx, wy = wny; } } } if (rev) { for (int i = 0; i < n; i++) a[i] /= n, b[i] /= n; } } int solve(ll a[], int na, ll b[], int nb, ll ans[]) { int len = max(na, nb), ln; for(ln = 0; L(ln) < len; ++ln); len = L(++ln); for (int i = 0; i < len ; ++i) { if (i >= na) ax[i] = 0, ay[i] = 0; else ax[i] = a[i], ay[i] = 0; } fft(ax, ay, len, 0); for (int i = 0; i < len; ++i) { if (i >= nb) bx[i] = 0, by[i] = 0; else bx[i] = b[i], by[i] = 0; } fft(bx, by, len, 0); for (int i = 0; i < len; ++i) { double cx = ax[i] * bx[i] - ay[i] * by[i]; double cy = ax[i] * by[i] + ay[i] * bx[i]; ax[i] = cx, ay[i] = cy; } fft(ax, ay, len, 1); for (int i = 0; i < len; ++i) ans[i] = (ll)(ax[i] + 0.5); return len; } #undef L(x)}const int maxn = 1e5 + 7;ll c[maxn << 2], d[maxn << 2], ans[maxn << 2], sum[maxn << 2];int a[maxn];int main() {#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin);#endif // ONLINE_JUDGE int T, n; cin >> T; while (T --) { fillchar(c, 0); fillchar(d, 0); fillchar(ans, 0); cin >> n; int maxv = 0; for (int i = 0; i < n; i ++) { RI(a[i]); c[a[i]] ++; umax(maxv, a[i]); } maxv ++; for (int i = 0; i < maxv; i ++) d[i] = c[i]; int L = FFT::solve(c, maxv, d, maxv, ans); while (ans[L] <= 0 && L > 1) L --; L ++; for (int i = 0; i < n; i ++) ans[a[i] << 1] --; for (int i = 1; i < L; i ++) { ans[i] >>= 1; sum[i] = sum[i - 1] + ans[i]; } ll Result = 0, Total = (ll)n * (n - 1) * (n - 2) / 6; //sort(a, a + n); for (int i = 0; i < n; i ++) { ll buf = sum[L - 1] - sum[a[i]]; buf -= n - 1; buf -= (ll)i * (n - i - 1); buf -= (ll)(n - i - 1) * (n - i - 2) / 2; Result += buf; } printf("%.7f\n", (double)Result / Total); } return 0;}/* ******************************************************************************** */ |
[hdu4609]计数方法,FFT的更多相关文章
- 【spring data jpa】jpa中使用count计数方法
spring data jpa中使用count计数方法很简单 直接在dao层写方法即可 int countByUidAndTenementId(String parentUid, String ten ...
- 【概率论】1-2:计数方法(Counting Methods)
title: [概率论]1-2:计数方法(Counting Methods) categories: Mathematic Probability keywords: Counting Methods ...
- 有标号的DAG计数(FFT)
有标号的DAG计数系列 有标号的DAG计数I 题意 给定一正整数\(n\),对\(n\)个点有标号的有向无环图(可以不连通)进行计数,输出答案\(mod \ 10007\)的结果.\(n\le 500 ...
- 【hdu4609】 3-idiots FFT
题外话:好久没写blog了啊-- 题目传送门 题目大意:给你m条长度为ai的线段,求在其中任选三条出来,能构成三角形的概率.即求在这n条线段中找出三条线段所能拼出的三角形数量除以$\binom{m}{ ...
- [HDU4609]3-idiots(生成函数+FFT)
3-idiots Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- php导出excel长数字串显示为科学计数方法与最终解决方法
1.设置单元格为文本 $objPHPExcel = new PHPExcel(); $objPHPExcel->setActiveSheetIndex(0); $objPHPExcel-> ...
- UOJ#335. 【清华集训2017】生成树计数 多项式,FFT,下降幂,分治
原文链接www.cnblogs.com/zhouzhendong/p/UOJ335.html 前言 CLY大爷随手切这种题. 日常被CLY吊打系列. 题解 首先从 pruffer 编码的角度考虑这个问 ...
- bzoj1272 Gate Of Babylon(计数方法+Lucas定理+乘法逆元)
Description Input Output Sample Input 2 1 10 13 3 Sample Output 12 Source 看到t很小,想到用容斥原理,推一下发现n种数中选m个 ...
- loj6570 毛毛虫计数(生成函数FFT)
link 巨佬olinr的题解 <-- olinr很强 考虑生成函数 考虑直径上点数>=4的毛毛虫的直径,考虑直径中间那些节点以及他上面挂的那些点的EGF \(A(x)=\sum_{i\g ...
随机推荐
- F - Bone Collector
Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like ...
- 代理模式是什么?如何在 C# 中实现代理模式
代理模式 并不是日常开发工作中常常用到的一种设计模式,也是一种不易被理解的一种设计模式.但是它会广泛的应用在系统框架.业务框架中. 定义 它的 定义 就如其它同大部分 设计模式 的定义类似,即不通俗也 ...
- Linux学习笔记(三)目录和文件都能操作的命令
目录和文件都能操作的命令 rm cp mv rm 英文原意:remove files or directories 功能:删除文件或目录 语法:rm 选项[-fir] 文件或目录 rm -f 强制删除 ...
- 前端学习笔记-H5
H5常用标签及其属性: <a>标签做超链接: <p>段落标签,自带段间距和换行样式: <div>块标签,表示一块内容,没有具体语意,区别与p标签,块与块间没有间距: ...
- Python爬虫入门(基础实战)—— 模拟登录知乎
模拟登录知乎 这几天在研究模拟登录, 以知乎 - 与世界分享你的知识.经验和见解为例.实现过程遇到不少疑问,借鉴了知乎xchaoinfo的代码,万分感激! 知乎登录分为邮箱登录和手机登录两种方式,通过 ...
- str_pad 和 filter_var
这两个函数都是php内置函数,filter_var可直接过滤,比如邮箱,ip等,str_pad可补充字符串eg: 1 => 001
- 2019-2020-1 20199308《Linux内核原理与分析》第七周作业
<Linux内核分析> 第六章 进程的描述和进程的创建 6.1 进程的描述 操作系统内核实现操作系统的三大管理功能: 进程管理(进程)-核心 内存管理(虚拟内存) 文件系统(文件) 为了管 ...
- Windows SDK 的 ctype.h 里有一些有用的函数,例如字符串的大小写转换
#define _tolower(c) ((c) - 'A' + 'a') #define _toupper(c) ((c) - 'a' + 'A')
- opencv-2-VS2017与QT显示图像
opencv-2-VS2017与QT显示图像 opencvqtVSC++ 目的 使用 VS 构建第一个 opencv 程序 使用 QT 构建 第一个 opencv 程序 VS 导入 QT 程序 开始 ...
- Java泛型和编译优化的一个例子
public class Main { public static void main(String[] args) { ArrayList<String> strList = new A ...