码迷,mamicode.com
首页 > 系统相关 > 详细

hdu 5730 Shell Necklace fft+cdq分治

时间:2016-07-22 12:40:13      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:

题目链接

 

dp[n] = sigma(a[i]*dp[n-i]), 给出a1.....an, 求dp[n]。 n为1e5.

 

这个式子的形式显然是一个卷积, 所以可以用fft来优化一下, 但是这样也是会超时的。 所以可以用cdq分治来优化。

cdq分治就是处理(l, mid)的时候, 将dp[l]...dp[mid]对dp[mid+1]...dp[r]做的贡献都算出来。

#include <bits/stdc++.h>

using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<11
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
typedef complex <double> cmx;
const int maxn = 2e5;
cmx x[maxn], y[maxn];
int a[maxn], dp[maxn], n;
void change(cmx x[], int len) {
    int i, j, k;
    for(i = 1, j = len/2; i < len - 1; i++) {
        if(i < j)
            swap(x[i], x[j]);
        k = len / 2;
        while(j >= k) {
            j -= k;
            k /= 2;
        }
        if(j < k)
            j += k;
    }
}
void fft(cmx x[], int len, int on) {
    change(x, len);
    for(int i = 2; i <= len; i <<= 1) {
        cmx wn(cos(-on * 2 * PI/i), sin(-on * 2 * PI/i));
        for(int j = 0; j < len; j += i) {
            cmx w(1, 0);
            for(int k = j; k < j + i/2; k++) {
                cmx u = x[k];
                cmx v = x[k + i/2]*w;
                x[k] = u + v;
                x[k+i/2] = u - v;
                w *= wn;
            }
        }
    }
    if(on == -1) {
        for(int i = 0; i < len; i++)
            x[i] /= len;
    }
}
void cdq(int l, int r)
{
    if(l == r) {
        dp[l] += a[l];
        dp[l] %= mod;
        return ;
    }
    int mid = l+r>>1;
    cdq(l, mid);
    int len = 1;
    while(len <= (r-l+1))
        len <<= 1;
    for(int i = 0; i < len; i++) {
        x[i] = y[i] = cmx(0, 0);
    }
    for(int i = l; i <= mid; i++) {
        x[i-l] = cmx(dp[i], 0);
    }
    for(int i = 1; i <= r-l; i++) {
        y[i-1] = cmx(a[i], 0);
    }
    fft(x, len, 1);
    fft(y, len, 1);
    for(int i = 0; i < len; i++)
        x[i] *= y[i];
    fft(x, len, -1);
    for(int i = mid+1; i <= r; i++) {
        dp[i] += (int)(x[i-l-1].real()+0.5);
        dp[i] %= mod;
    }
    cdq(mid+1, r);
}
int main()
{
    while(scanf("%d", &n) && n) {
        mem(dp);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            a[i] %= mod;
        }
        cdq(1, n);
        cout<<dp[n]<<endl;
    }
}

 

hdu 5730 Shell Necklace fft+cdq分治

标签:

原文地址:http://www.cnblogs.com/yohaha/p/5694679.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!