HDU 4609 3-idiots ——(FFT)
这是我接触的第一个关于FFT的题目,留个模板。
这题的题解见:http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html。
FFT的模板如下:
#include<bits/stdc++.h>
using namespace std;
const double pi = atan(1.0)*;
struct Complex {
double x,y;
Complex(double _x=,double _y=)
:x(_x),y(_y) {}
Complex operator + (Complex &tt) { return Complex(x+tt.x,y+tt.y); }
Complex operator - (Complex &tt) { return Complex(x-tt.x,y-tt.y); }
Complex operator * (Complex &tt) { return Complex(x*tt.x-y*tt.y,x*tt.y+y*tt.x); }
};
Complex a[],b[];
void fft(Complex *a, int n, int rev) {
// n是(大于等于相乘的两个数组长度)2的幂次 ; 比如长度是5 ,那么 n = 8 2^2 < 5 2^3 > 5
// 从0开始表示长度,对a进行操作
// rev==1进行DFT,==-1进行IDFT
for (int i = ,j = ; i < n; ++ i) {
for (int k = n>>; k > (j^=k); k >>= );
if (i<j) std::swap(a[i],a[j]);
}
for (int m = ; m <= n; m <<= ) {
Complex wm(cos(*pi*rev/m),sin(*pi*rev/m));
for (int i = ; i < n; i += m) {
Complex w(1.0,0.0);
for (int j = i; j < i+m/; ++ j) {
Complex t = w*a[j+m/];
a[j+m/] = a[j] - t;
a[j] = a[j] + t;
w = w * wm;
}
}
}
if (rev==-) {
for (int i = ; i < n; ++ i) a[i].x /= n,a[i].y /= n;
}
}
int main(){
a[] = Complex(,); // a[0]: x的0次项。
a[] = Complex(,);
a[] = Complex(,);
a[] = Complex(,); b[] = Complex(,);
b[] = Complex(,);
b[] = Complex(,);
b[] = Complex(,);
fft(a,,);
fft(b,,);
for(int i = ; i < ; i ++){
a[i] = a[i] * b[i];
}
fft(a,,-);
for(int i = ; i < ; i ++){
cout << i << " " << a[i].x << endl;;
}
/*
* fft:nlogn求两个多项式相乘,(原来要n^2)
*
* f1 = 0x^0 + 1x^1 + 2x^2 + 3x^3
* f2 = 3 + 2x^1 + x^2 + 0x^3;
*
* f1 = a + b + c + d;
* f2 = x + y + z + k;
* f3 = __
* dp[1] dp[2] dp[3] dp[4] dp[5];
* c[0] c[1] c[2] c[3];
*/
/*
0 0 * x^0
1 3 * x^1
2 8 * x^2
3 14
4 8 -----> 0x^0 + 3x^1 + 8x^2 ...... 3x^5
5 3
6 0 * x^6
7 0 * x^7
* */
return ;
}
FFT模板
关于这个模板有几点需要注意的:
1.在系数转化成整数时,会有精度误差,需要加eps。
2.假设a和b之前的长度都是n,卷积以后的大小应该是2*n-1,再考虑到fft中第二个参数n必须是大于等于卷积长度的2的幂次,因此最后的数组长度必须是n的4倍,也就是说这里的a数组大小应该开4倍才行。
3.注意在对a和b进行fft(a, LIM, 1)之前需要对n+1~LIM之间的复数也初始化为Complex(0, 0)以免多组测试中之前的操作对当前的操作产生影响。
最后,本题的AC代码如下:
#include<bits/stdc++.h>
using namespace std;
const double pi = atan(1.0)*;
const int N = 1e5 + ;
typedef long long ll; struct Complex {
double x,y;
Complex(double _x=,double _y=)
:x(_x),y(_y) {}
Complex operator + (Complex &tt) { return Complex(x+tt.x,y+tt.y); }
Complex operator - (Complex &tt) { return Complex(x-tt.x,y-tt.y); }
Complex operator * (Complex &tt) { return Complex(x*tt.x-y*tt.y,x*tt.y+y*tt.x); }
};
Complex a[N*],b[N];
void fft(Complex *a, int n, int rev) {
// n是(大于等于相乘的两个数组长度)2的幂次 ; 比如长度是5 ,那么 n = 8 2^2 < 5 2^3 > 5
// 从0开始表示长度,对a进行操作
// rev==1进行DFT,==-1进行IDFT
for (int i = ,j = ; i < n; ++ i) {
for (int k = n>>; k > (j^=k); k >>= );
if (i<j) std::swap(a[i],a[j]);
}
for (int m = ; m <= n; m <<= ) {
Complex wm(cos(*pi*rev/m),sin(*pi*rev/m));
for (int i = ; i < n; i += m) {
Complex w(1.0,0.0);
for (int j = i; j < i+m/; ++ j) {
Complex t = w*a[j+m/];
a[j+m/] = a[j] - t;
a[j] = a[j] + t;
w = w * wm;
}
}
}
if (rev==-) {
for (int i = ; i < n; ++ i) a[i].x /= n,a[i].y /= n;
}
} int A[N];
ll num[N*], sum[N*]; int main(){
/*a[0] = Complex(0,0); // a[0]: x的0次项。
a[1] = Complex(1,0);
a[2] = Complex(2,0);
a[3] = Complex(3,0); b[0] = Complex(3,0);
b[1] = Complex(2,0);
b[2] = Complex(1,0);
b[3] = Complex(0,0);
fft(a,8,1);
fft(b,8,1);
for(int i = 0 ; i < 8 ; i ++){
a[i] = a[i] * b[i];
}
fft(a,8,-1);
for(int i = 0 ; i < 8 ; i ++){
cout << i << " " << a[i].x << endl;;
}*/
//a[0] = Complex(0, 0); b[0] = Complex(0, 0);
int T; scanf("%d",&T);
while(T--)
{
int n; scanf("%d",&n);
memset(num,,sizeof num);
for(int i=;i<=n;i++)
{
scanf("%d",A+i);
num[A[i]]++;
}
sort(A+, A++n);
int len = A[n];
int LIM = ;
while()
{
if(LIM >= len*+) break;
else LIM <<= ;
}
for(int i=;i<=len;i++)
{
a[i] = Complex(num[i], );
}
for(int i=len+;i<LIM;i++)
{
a[i] = Complex(, );
}
fft(a,LIM,);
for(int i=;i<LIM;i++) a[i] = a[i] * a[i];
fft(a,LIM,-);
// finish fft
len = len * ;
for(int i=;i<=len;i++) num[i] = (ll)(a[i].x + 0.5);
for(int i=;i<=n;i++) num[A[i]*]--; // 减去两个相同的组合
for(int i=;i<=len;i++) num[i] /= ; // 选择的是无序的
for(int i=;i<=len;i++) sum[i] = sum[i-] + num[i];
ll ans = ;
for(int i=;i<=n;i++)
{
int now = A[i];
ans += sum[len] - sum[now]; // 对于每个数,加起来比它大的都是可行的
ans -= 1LL * (i-) * (n-i); // 减去一个大的一个小的组合的情况
ans -= 1LL * (n-); // 减去自己和任意一个组合的情况
ans -= 1LL * (n-i) * (n-i-) / ; // 减去比它大的两个组合的情况
// 剩下的就是两个小的加起来比A[i]大的情况
}
ll all = 1LL * n*(n-)*(n-) / ;
printf("%.7f\n",1.0*ans/all);
}
return ;
}
AC代码
HDU 4609 3-idiots ——(FFT)的更多相关文章
- HDU 5763 Another Meaning(FFT)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5763 [题目大意] 给出两个串S和T,可以将S串中出现的T替换为*,问S串有几种表达方式. [题解 ...
- 2019.01.02 bzoj3513: [MUTC2013]idiots(fft)
传送门 fftfftfft经典题. 题意简述:给定nnn个长度分别为aia_iai的木棒,问随机选择3个木棒能够拼成三角形的概率. 思路:考虑对于木棒构造出生成函数然后可以fftfftfft出两个木 ...
- A * B Problem Plus HDU - 1402 (FFT)
A * B Problem Plus HDU - 1402 (FFT) Calculate A * B. InputEach line will contain two integers A and ...
- 快速傅里叶(FFT)的快速深度思考
关于按时间抽取快速傅里叶(FFT)的快速理论深度思考 对于FFT基本理论参考维基百科或百度百科. 首先谈谈FFT的快速何来?大家都知道FFT是对DFT的改进变换而来,那么它究竟怎样改进,它改进的思想在 ...
- HDU 5938 Four Operations(四则运算)
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- HDU 5775 Bubble Sort(冒泡排序)
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- HDU 1711 Number Sequence(数列)
HDU 1711 Number Sequence(数列) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- HDU 1005 Number Sequence(数列)
HDU 1005 Number Sequence(数列) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav ...
- 【BZOJ3527】力(FFT)
[BZOJ3527]力(FFT) 题面 Description 给出n个数qi,给出Fj的定义如下: \[Fj=\sum_{i<j}\frac{q_i q_j}{(i-j)^2 }-\sum_{ ...
- 【BZOJ4827】【HNOI2017】礼物(FFT)
[BZOJ4827][HNOI2017]礼物(FFT) 题面 Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每 ...
随机推荐
- JS定时器做物体运动
JS定时器是函数 setInterval(函数体/函数名 , 时间) 清楚定时器 clearInterval(函数) 时间单位(毫秒) 1000毫秒 = 1秒 首先我们要知道用JS定时器能干什么? ...
- stm32 视频小车
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ...
- Computer Vision_33_SIFT:TILDE: A Temporally Invariant Learned DEtector——2014
此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...
- Python 获取环境变量的几种方式
第一种 import os os.environ.get('key_name') 第二种 import os os.getenv('key_name') 第三种 import os os.getenv ...
- TLS握手秘钥套件分析
1.为了弄清楚TLS1.3的内部结构,觉得有必要将TLS的整个结构从新整理一遍,方便后续在做握手协议的形式化分析的时候能够不遗漏每个加密和认证的的环节. TLS1.3不论文在协议内容上还是性能上都较之 ...
- Python基础——细琐知识点
注释 Python注释有两种方式 使用# 类似于Shell脚本的注释方式,单行注释 使用'''或者""" 使用成对的'''或者""".这种注 ...
- 静态库 VS 动态库
如何得到库 ①先写好一堆的.c文件(.c:我们所需要的各种工具函数) ②将这些.c编译为对应的.o ③将所有的这些.o打包为一个仓库文件(静态库或者动态库) 静态库:按照静态库的方式打包 动态库:按照 ...
- 数据库管理工具-Navicat Premium 12
首先感谢下github上大佬,我才能使用这个软件.也可以直接浏览https://github.com/DoubleLabyrinth/navicat-keygen进行安装,非常详细. 1.https: ...
- 2019招商银行M-Geeker线上比赛题解析
目录 1. 最大子序和(变体) 2. 矩阵求乘积最大 3. 逐渐平均--值最大 目前已更新:第一题,第二题,第四题 1. 最大子序和(变体) 题目描述: 首先考虑常规的最大子序和的问题,即不能去掉中间 ...
- Castle.Windsor依赖注入的高级应用与生存周期
1. 使用代码方式进行组件注册[依赖服务类] using System; using System.Collections.Generic; using System.Linq; using Syst ...