【FFT】HDU 5307 He is Flying

通道: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分成很多段。

代码:

  感谢沈洋点拨。

  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 */
View Code

 

 

附学习资料

转载于:https://www.cnblogs.com/Rojo/p/4671560.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值