[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 }

 

posted @ 2016-12-04 11:51  Kirai  阅读(306)  评论(0编辑  收藏  举报