Topic links
Dp[n] = Sigma (A[i]*dp[n-i]), given a1.....an, Dp[n]. N is 1e5.
The form of this equation is obviously a convolution, so you can use the FFT to optimize it, but this will also time out. So you can use the CDQ to optimize the partition.
CDQ Division is to deal with (L, mid) when, will Dp[l]...dp[mid] to Dp[mid+1]...dp[r] to do the contribution of the calculation.
#include <bits/stdc++.h>using namespacestd;#definePB (x) push_back (x)#definell Long Long#defineMK (x, y) make_pair (x, y)#defineLson L, M, rt<<1#defineMem (a) memset (a, 0, sizeof (a))#defineRson m+1, R, rt<<11#defineMem1 (a) memset (a,-1, sizeof (a))#defineMEM2 (a) memset (a, 0x3f, sizeof (a))#defineRep (i, N, a) for (int i = A; i<n; i++)#defineFi first#defineSe Secondtypedef pair<int,int>PLL;Const DoublePI = ACOs (-1.0);Const DoubleEPS = 1e-8;Const intMoD = 1e9+7;Const intINF =1061109567;Const intdir[][2] = { {-1,0}, {1,0}, {0, -1}, {0,1}};typedef Complex<Double>CMX;Const intMAXN =2e5;cmx X[MAXN], Y[MAXN];intA[MAXN], DP[MAXN], N;voidChange (CMX x[],intLen) { intI, 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; }}voidFFT (CMX x[],intLenintOn ) {Change (x, Len); for(inti =2; I <= Len; I <<=1) {cmx wn (cos (-on *2* pi/i), sin (-on *2* pi/i)); for(intj =0; J < Len; J + =i) {CMX W (1,0); for(intK = 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(inti =0; i < Len; i++) X[i]/=Len; }}voidCdqintLintR) { if(L = =R) {Dp[l]+=A[l]; DP[L]%=MoD; return ; } intMID = L+r>>1; CDQ (L, mid); intLen =1; while(Len <= (r-l+1)) Len<<=1; for(inti =0; i < Len; i++) {X[i]= Y[i] = CMX (0,0); } for(inti = l; I <= mid; i++) {X[i-L] = CMX (Dp[i],0); } for(inti =1; I <= r-l; i++) {Y[i-1] = CMX (A[i],0); } FFT (x, Len,1); FFT (y, Len,1); for(inti =0; i < Len; i++) X[i]*=Y[i]; FFT (x, Len,-1); for(inti = mid+1; I <= R; i++) {Dp[i]+= (int) (x[i-l-1].real () +0.5); Dp[i]%=MoD; } CDQ (Mid+1, R);}intMain () { while(SCANF ("%d", &n) &&N) {mem (DP); for(inti =1; I <= N; i++) {scanf ("%d", &A[i]); A[i]%=MoD; } CDQ (1, N); cout<<dp[n]<<Endl; }}
HDU 5730 Shell Necklace FFT+CDQ Division