zoukankan      html  css  js  c++  java
  • hdu 5730 Shell Necklace fft+cdq分治

    题目链接

    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;
        }
    }
  • 相关阅读:
    如何解决Pulling without specifying how to reconcile divergent branches
    Mac设置终端打开快捷键
    Mac 息屏快捷键
    Windows安装使用Openssl
    tomcat证书转换成nginx证书。jks/keystore > crt/key
    Windows下类似Linux的CAT命令是什么
    齐文词根词缀---3.23、co-(放在元音前面)表示共同,(和com和con一个意思)
    齐文词根词缀---3.22、clus-关闭(就是close)
    齐文词根词缀---3.21、clam/claim-喊
    齐文词根词缀---3.20、cis-切、割(同cid)
  • 原文地址:https://www.cnblogs.com/yohaha/p/5694679.html
Copyright © 2011-2022 走看看