通道:http://acm.hdu.edu.cn/showproblem.php?pid=5307
题意:给出n个数,然后求所有的dp[i],这里的dp[i]就是所有连续区间内和为i的区间长度总和
思路:cnt[i]*sum[i]的卷积就可以了,cnt[i]代表和为i的个数,sum[i]为和为i的区间长度,答案就是buf[m+i]-buf[m-i],原因就是会发现这些点可以按sigma s分成很多段。
代码:
感谢沈洋点拨。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 8 typedef long long ll; 9 10 const int MAX_N = 100007; 11 const int MAX_M = 100007; 12 const long double PI = acos(-1.0); 13 14 struct Complex { 15 long double r, i; 16 Complex(long double _r, long double _i) { 17 r = _r; 18 i = _i; 19 } 20 Complex operator + (const Complex &c) { 21 return Complex(c.r + r, c.i + i); 22 } 23 Complex operator - (const Complex &c) { 24 return Complex(r - c.r, i - c.i); 25 } 26 Complex operator * (const Complex &c) { 27 return Complex(c.r * r - c.i * i, c.r * i + c.i * r); 28 } 29 Complex operator / (const int &c) { 30 return Complex(r / c, i / c); 31 } 32 Complex(){} 33 }; 34 namespace FFT { 35 int rev(int id, int len) { 36 int ret = 0; 37 for(int i = 0; (1 << i) < len; ++i) { 38 ret <<= 1; 39 if(id & (1 << i)) ret |= 1; 40 } 41 return ret; 42 } 43 Complex A[MAX_M << 3]; 44 void FFT(Complex *a, int len, int DFT) { 45 for(int i = 0; i < len; ++i) A[rev(i, len)] = a[i]; 46 for(int s = 1; (1 << s) <= len; ++s) { 47 int m = (1 << s); 48 Complex wm = Complex(cos(PI * DFT * 2 / m), sin(PI * DFT * 2 / m)); 49 for(int k = 0; k < len; k += m) { 50 Complex w = Complex(1, 0); 51 for(int j = 0; j < (m >> 1); j++) { 52 Complex t = w * A[k + j + (m >> 1)]; 53 Complex u = A[k + j]; 54 A[k + j] = u + t; 55 A[k + j + (m >> 1)] = u - t; 56 w = w * wm; 57 } 58 } 59 } 60 if(DFT == -1) for(int i = 0; i < len; ++i) A[i] = A[i] / len; 61 for(int i = 0; i < len; i++) a[i] = A[i]; 62 } 63 }; 64 65 int n, m, d[MAX_N], cnt[MAX_N]; 66 ll sum[MAX_N], buf[MAX_N]; 67 Complex A[MAX_M << 3], B[MAX_M << 3]; 68 69 void run() { 70 scanf("%d", &n); 71 d[0] = 0; 72 for (int i=1; i<=n; ++i) scanf("%d", &d[i]), d[i] += d[i-1]; 73 m = d[n]; 74 for (int i=0; i<=m; ++i) cnt[i] = sum[i] = 0; 75 for (int i=0; i<=n; ++i) ++cnt[d[i]], sum[d[i]] += i; 76 int len = 1; 77 while (len <= m) len <<= 1; len <<= 1; 78 for (int i = 0; i <= m; ++i) A[i] = Complex(sum[i], 0), B[i] = Complex(cnt[m - i], 0); 79 for (int i = m + 1; i < len; ++i) A[i] = B[i] = Complex(0, 0); 80 FFT::FFT(A, len, 1); FFT::FFT(B, len, 1); 81 for (int i = 0; i < len; ++i) A[i] = A[i] * B[i]; 82 FFT::FFT(A, len, -1); 83 for (int i = 0; i < len; ++i) buf[i] = (ll)(A[i].r + 0.5); 84 ll ans0 = 0; 85 for (int i=0; i<=m; ++i) 86 for (int j=1; j<cnt[i]; ++j) 87 ans0 += (ll)j * (cnt[i] - j); 88 printf("%I64d\n", ans0); 89 for (int i=1; i<=m; ++i) 90 printf("%I64d\n", buf[m + i] - buf[m - i]); 91 } 92 int main() { 93 int T; scanf("%d", &T); 94 while (T--) run(); 95 return 0; 96 } 97 98 /* 99 100 100 101 7 102 1 1 2 1 0 1 2 103 104 */