[HRBUSTOJ1476]Pairs(FFT)

题目链接:http://acm-software.hrbust.edu.cn/problem.php?id=1476

题意:给n个数,m次询问,每次询问一个k。问n个数里两数之和严格小于k的数对。

根据输入样例,无非是需要求:

f = cnt(1 2 3 4 5)T * (x)(其中(x)代表1,x,x^2...的向量,cnt表示这些数出现的次数,T表示转置)自乘一次后对应x幂次前的系数,取前k-1项系数和就是答案。复杂度太高了,O(n^2)的系数搞法是不可以的,所以需要搞成点值表达DFT后再IDFT回来。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 const double PI = acos(-1.0);
 5 typedef struct Complex {
 6     double r,i;
 7     Complex(double _r = 0.0,double _i = 0.0) {
 8         r = _r; i = _i;
 9     }
10     Complex operator +(const Complex &b) {
11         return Complex(r+b.r,i+b.i);
12     }
13     Complex operator -(const Complex &b) {
14         return Complex(r-b.r,i-b.i);
15     }
16     Complex operator *(const Complex &b) {
17         return Complex(r*b.r-i*b.i,r*b.i+i*b.r);
18     }
19 }Complex;
20
21 void change(Complex y[],int len) {
22     int i,j,k;
23     for(i = 1, j = len/2;i < len-1; i++) {
24         if(i < j)swap(y[i],y[j]);
25         k = len/2;
26         while( j >= k) {
27             j -= k;
28             k /= 2;
29         }
30         if(j < k) j += k;
31     }
32 }
33
34 void fft(Complex y[],int len,int on) {
35     change(y,len);
36     for(int h = 2; h <= len; h <<= 1) {
37         Complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
38         for(int j = 0;j < len;j+=h) {
39             Complex w(1,0);
40             for(int k = j;k < j+h/2;k++) {
41                 Complex u = y[k];
42                 Complex t = w*y[k+h/2];
43                 y[k] = u+t;
44                 y[k+h/2] = u-t;
45                 w = w*wn;
46             }
47         }
48     }
49     if(on == -1) {
50         for(int i = 0;i < len;i++) {
51             y[i].r /= len;
52         }
53     }
54 }
55
56 const int maxn = 400040;
57 typedef long long LL;
58 int a[maxn];
59 Complex c[maxn];
60 LL f[maxn];
61 int n, m;
62
63 int main() {
64     // freopen("in", "r", stdin);
65     int T;
66     scanf("%d", &T);
67     while(T--) {
68         memset(f, 0, sizeof(f));
69         scanf("%d%d",&n,&m);
70         int maxx = -1;
71         for(int i = 0; i < n; i++) {
72             scanf("%d", &a[i]);
73             maxx = max(a[i], maxx);
74             f[a[i]]++;
75         }
76         int len1 = maxx + 1;
77         int len = 1;
78         while(len < 2 * len1) len <<= 1;
79         for(int i = 0; i < len; i++) c[i] = Complex(0, 0);
80         for(int i = 0; i < len1; i++) c[i] = Complex(f[i], 0);
81         fft(c, len, 1);
82         for(int i = 0; i < len; i++) c[i] = c[i] * c[i];
83         fft(c, len, -1);
84         for(int i = 0; i < len; i++) f[i] = (LL)(c[i].r + 0.5);
85         len = 2 * maxx;
86         for(int i = 0; i < n; i++) f[a[i]*2]--;
87         for(int i = 1; i <= len; i++) {
88             f[i] /= 2;
89             f[i] += f[i-1];
90         }
91         while(m--) {
92             int k;
93             scanf("%d", &k);
94             printf("%lld\n", f[k-1]);
95         }
96     }
97     return 0;
98 }
时间: 2024-10-08 02:14:57

[HRBUSTOJ1476]Pairs(FFT)的相关文章

快速傅里叶变换(FFT)

快速傅里叶变换(FFT)算法[详解] 快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.我打开一本老旧的算法书,欣赏了JW Cooley 和 John Tukey 在1965年的文章中,以看似简单的计算技巧来讲解这个东西. 本文的目标是,深入Cooley-Tukey  FFT 算法,解释作为其根源的"对称性",并以一些直观的python代码将其理论转变为实际.我希望这次研究能对这个算法的背景原理有更全面的认识. FFT(快速傅里叶

Hdu 1402 (FFT)

题目链接 A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 12490    Accepted Submission(s): 2206 Problem Description Calculate A * B. Input Each line will contain two integers A and

洛谷P3803 【模板】多项式乘法(FFT)

P3803 [模板]多项式乘法(FFT) 题目背景 这是一道FFT模板题 题目描述 给定一个n次多项式F(x),和一个m次多项式G(x). 请求出F(x)和G(x)的卷积. 输入输出格式 输入格式: 第一行2个正整数n,m. 接下来一行n+1个数字,从低到高表示F(x)的系数. 接下来一行m+1个数字,从低到高表示G(x))的系数. 输出格式: 一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数. 输入输出样例 输入样例#1: 复制 1 2 1 2 1 2 1 输出样例#1: 复制 1

BZOJ[3527],[ZJOI2014]力(FFT)

BZOJ[3527],[ZJOI2014]力(FFT) 题意: 给出\(n\)个数\(q_i\),给出\(Fj\)的定义如下: \(F_j=\sum \limits _ {i < j} \frac{q_iq_j}{(i-j)^2}-\sum \limits _{i >j} \frac{q_iq_j}{(i-j)^2}.\) 令\(E_i=F_i/q_i\),求\(E_i\). 题解: 一开始没发现求\(E_i\)... 其实题目还更容易想了... \(E_i=\sum\limits _{j&l

【知识总结】快速傅里叶变换(FFT)

这可能是我第五次学FFT了--菜哭qwq 先给出一些个人认为非常优秀的参考资料: 一小时学会快速傅里叶变换(Fast Fourier Transform) - 知乎 小学生都能看懂的FFT!!! - 胡小兔 - 博客园 快速傅里叶变换(FFT)用于计算两个\(n\)次多项式相乘,能把复杂度从朴素的\(O(n^2)\)优化到\(O(nlog_2n)\).一个常见的应用是计算大整数相乘. 本文中所有多项式默认\(x\)为变量,其他字母均为常数.所有角均为弧度制. 一.多项式的两种表示方法 我们平时常

HDU 4609 3-idiots(FFT)

题意:给出n个正整数(数组A).每次随机选出三个数.问这三个数能组成三角形的概率为多大? 首先,我们用类似桶排计数的方法作出两个数组a,b,储存每个长度有几条边,然后对两个数组求卷积. 求出卷积后,这就代表了2条边能构成的边长度的集合了,注意,由于求卷积的时候可能把两条相同的边相加,所以最后求出的数组一定要减去这重复的部分,然后,先算x后算y等价于先算y后算x,所以要除以二. 然后,对于第三条边a[i],我们这样考虑:令它作为这三条边中最大的那条! 所以之前的卷积求出来的两边和一定会比这条边大,

傅里叶变换(FFT)的多相滤波结构实现

作者:桂. 时间:2017-09-25  14:53:01 链接:http://www.cnblogs.com/xingshansi/p/7591868.html 前言 以前在梳理信号频域变换的时候,提到逆序级联FFT(Inverse cascade FFT)的实现思路,后来分析多相滤波信道化,才发现其实Cascade FFT就是FFT的多相结构实现,在此系统梳理一下. 一.多相结构FFT实现 A-传统测频技术分析 信号的短时傅里叶变换(STFT)可表示为: 其中s为输入信号,w为对应窗函数.长

【ZOJ 3856】Goldbach(FFT)

题意:最多使用三个质数做加法和乘法,问得到X有多少种方案. 这道题的话分几种情况讨论清楚就好了. 1.只有一个数的情况,如果这个数是质数则方案数加1 2.有两个数的情况,可以将两个数做加法和乘法,加法的话将质数得到的数字做一遍FFT,乘法直接做sqrt(n) * sqrt(n)就好了 3.有三个数的情况,分别有三种方法,分别是a + b + c, a + b * c,a * b * c 对于a * b * c,暴力遍历一遍就好,对于a + b * c,首先暴力遍历下b * c,然后再将一个数的两

GYM 101667H Rock Paper Scissors(FFT)

题意:给你一个串a,是有R,S,P(石头剪刀布)构成的,然后还有一个序列b是你的出牌顺序,但你可以跳过机器的前x个出牌,从x+1开始出,问你最多赢几次 思路:好烦啊,这个题下午一直不会做,感觉和之前学弟将的一个模糊匹配的很像,但好像也不怎么像,挂机一下午. 这个题其实是利用了卷积的性质,我们先考虑单独的每一个字母,因为我们在卷积的时候不能牵扯其他的字符,如果有其他的字符,就类似于模糊匹配了,那是我们只是用FFT加速多项式乘法,而这道题的FFT其实是用FFT算出对于(FFT后的)第i个位置,我们字