洛谷P3338 力
题意:
解:
介绍两种方法。
首先可以把那个最后除的qi拆掉。
①分前后两部分处理。
前一部分可以看做是个卷积。下面的平方不拆开,直接看成gi-j即可。
后一部分按照套路,把循环变量改成从0开始,反转q,之后也是卷积。
②直接构造函数卷积。
题解。
我写的第一种。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 5 const int N = 100010; 6 const double pi = 3.1415926535897932384626; 7 8 struct cp { 9 double x, y; 10 cp(double X = 0, double Y = 0) { 11 x = X; 12 y = Y; 13 } 14 inline cp operator +(const cp &w) const { 15 return cp(x + w.x, y + w.y); 16 } 17 inline cp operator -(const cp &w) const { 18 return cp(x - w.x, y - w.y); 19 } 20 inline cp operator *(const cp &w) const { 21 return cp(x * w.x - y * w.y, x * w.y + y * w.x); 22 } 23 }f[N << 2], g[N << 2], h[N << 2]; 24 25 int r[N << 2]; 26 27 inline void FFT(int n, cp *a, int f) { 28 for(int i = 0; i < n; i++) { 29 if(i < r[i]) { 30 std::swap(a[i], a[r[i]]); 31 } 32 } 33 34 for(int len = 1; len < n; len <<= 1) { 35 cp Wn(cos(pi / len), f * sin(pi / len)); 36 for(int i = 0; i < n; i += (len << 1)) { 37 cp w(1, 0); 38 for(int j = 0; j < len; j++) { 39 cp t = a[i + len + j] * w; 40 a[i + len + j] = a[i + j] - t; 41 a[i + j] = a[i + j] + t; 42 w = w * Wn; 43 } 44 } 45 } 46 47 if(f == -1) { 48 for(int i = 0; i <= n; i++) { 49 a[i].x /= n; 50 } 51 } 52 return; 53 } 54 55 int main() { 56 int n; 57 scanf("%d", &n); 58 n--; 59 for(int i = 0; i <= n; i++) { 60 scanf("%lf", &f[i].x); 61 h[n - i].x = f[i].x; 62 } 63 g[0].x = 1; 64 for(int i = 1; i <= n; i++) { 65 g[i].x = ((double)(1)) / i / i; 66 } 67 68 int len = 2, lm = 1; 69 while(len <= n + n) { 70 len <<= 1; 71 lm++; 72 } 73 for(int i = 1; i <= len; i++) { 74 r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lm - 1)); 75 } 76 77 FFT(len, f, 1); 78 FFT(len, g, 1); 79 FFT(len, h, 1); 80 for(int i = 0; i <= len; i++) { 81 f[i] = f[i] * g[i]; 82 g[i] = g[i] * h[i]; 83 } 84 FFT(len, f, -1); 85 FFT(len, g, -1); 86 87 for(int i = 0; i <= n; i++) { 88 printf("%lf\n", f[i].x - g[n - i].x); 89 } 90 91 return 0; 92 }