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; } }