bzoj2194 快速傅里叶之二

题意:对于k = 0 ... n求

解:

首先把i变成从0开始

我们发现a和b的次数(下标)是成正比例的,这不可,于是反转就行了。

反转b的话,会发现次数和是n + k,这不可。

反转a就很吼了。

这个东西恰好是卷积出来的第n - k项的系数。

所以我们把a串反转,然后用a与b卷积,最后再反转输出即可。

 1 /**************************************************************
 2     Problem: 2194
 3     Language: C++
 4     Result: Accepted
 5     Time:133643896 ms
 6     Memory:14342474884 kb
 7 ****************************************************************/
 8  
 9 #include <cstdio>
10 #include <algorithm>
11 #include <cmath>
12 #include <cstring>
13  
14 const int N = 100010;
15 const double pi = 3.1415926535897932384626;
16  
17 struct cp {
18     double x, y;
19     cp(double X = 0, double Y = 0) {
20         x = X;
21         y = Y;
22     }
23     inline cp operator +(const cp &w) const {
24         return cp(x + w.x, y + w.y);
25     }
26     inline cp operator -(const cp &w) const {
27         return cp(x - w.x, y - w.y);
28     }
29     inline cp operator *(const cp &w) const {
30         return cp(x * w.x - y * w.y, x * w.y + y * w.x);
31     }
32 }a[N << 2], b[N << 2];
33  
34 int r[N << 2];
35  
36 inline void FFT(int n, cp *a, int f) {
37     for(int i = 0; i < n; i++) {
38         if(i < r[i]) {
39             std::swap(a[i], a[r[i]]);
40         }
41     }
42      
43     for(int len = 1; len < n; len <<= 1) {
44         cp Wn(cos(pi / len), f * sin(pi / len));
45         for(int i = 0; i < n; i += (len << 1)) {
46             cp w(1, 0);
47             for(int j = 0; j < len; j++) {
48                 cp t = a[i + len + j] * w;
49                 a[i + len + j] = a[i + j] - t;
50                 a[i + j] = a[i + j] + t;
51                 w = w * Wn;
52             }
53         }
54     }
55      
56     if(f == -1) {
57         for(int i = 0; i <= n; i++) {
58             a[i].x /= n;
59         }
60     }
61     return;
62 }
63  
64 int main() {
65     int n;
66     scanf("%d", &n);
67     n--;
68     for(int i = 0; i <= n; i++) {
69         scanf("%lf%lf", &a[n - i].x, &b[i].x);
70     }
71      
72     int len = 2, lm = 1;
73     while(len <= (n << 1)) {
74         len <<= 1;
75         lm++;
76     }
77     for(int i = 1; i <= len; i++) {
78         r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lm - 1));
79     }
80      
81     FFT(len, a, 1);
82     FFT(len, b, 1);
83     for(int i = 0; i <= len; i++) {
84         a[i] = a[i] * b[i];
85     }
86     FFT(len, a, -1);
87      
88     for(int i = 0; i <= n; i++) {
89         printf("%d\n", (int)(a[n - i].x + 0.5));
90     }
91      
92     return 0;
93 }
AC代码

 

posted @ 2019-01-10 10:12  huyufeifei  阅读(105)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

ReadEra 阅读书籍

『Flyable Heart 応援中!』