Tag: while void \ n Const floor How long def length
Topic
Briefly:
There is a shell of length n, divides it into several segments, gives the number of schemes divided into each length, and asks how many kinds of partitioning schemes
Exercises
Set \ (f[i]\) indicates the number of scenarios when the length is \ (i\)
The DP equation is not rare:
\[f[i] = \sum\limits_{j=0}^{i} a[j] * f[i-j]\]
Consider transfer
The direct transfer is \ (O (n^2) \)
How to optimize?
It is easy to find that the transfer equation is very special and is a convolution form
Consider FFT
Divide and conquer FFT
Divide-and-conquer FFT solves the problem of fast computation of such a transfer equation.
\[f[i] = \sum\limits_{j=0}^{i} a[j] * f[i-j]\]
Consider the model of CDQ Division:
We first deal with the left half interval, and then we use the \ (f[i]\) of the left half interval to update the answer of the right half interval.
Specifically, the contribution of the left half to the right one position \ (r\) is:
\[\SUM\LIMITS_{I=L}^{MID} f[i] * a[r-i]\]
is also a convolution form, the first \ (r\) item of the polynomial product
So we can use \ (f[i]\) and \ (a[i]\) constructs two polynomial, makes the FFT, then directly accumulates the corresponding position the value to the right half corresponding position \ (f[i]\) to go
We solved the problem.
#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#define LL Long Long int#define Redge (U) for (int k = h[u],to; k; k = ed[k].nxt)#define REP (i,n) for (int i = 1; I <= (n); i++)#define BUG (s,n) for (int i = 1; I <= (n); i++) cout<<s[i]<< '; puts ("");using namespaceStdConst intMAXN =400005, MAXM =100005, INF =1000000000, P =313;inline intRead () {intout =0, flag =1;Charc = GetChar (); while(C < -|| C > $){if(c = ='-') flag =-1; c = GetChar ();} while(c >= -&& C <= $) {out = (out <<3) + (out <<1) + C- -; c = GetChar ();}returnOut * FLAG;}Const DoublePI = ACOs (-1);structe{DoubleR,i; E () {} e (DoubleADoubleb): R (a), I (b) {} Eoperator=(Const int& B) {r = b; i =0;return* This; }};inlineEoperator+(Conste& A,Conste& b) {returnE (A.R + b.r,a.i + b.i);}inlineEoperator-(Conste& A,Conste& b) {returnE (A.R-B.R,A.I-B.I);}inlineEoperator*(Conste& A,Conste& b) {returnE (A.R * B.R-A.I * B.I,A.R * B.I + B.R * a.i);}inlineEoperator*= (e& A,Conste& b) {return(A = a * b);}inlineEoperator/(e& A,Const Double& B) {returnE (a.r/b,a.i/b);}inlineEoperator/= (e& A,Const Double& B) {return(A = A/b);}intN,M,L,R[MAXN];voidFFT (e* A,intf) { for(inti =0; I < n; i++)if(I < r[i]) swap (a[i],a[r[i]); for(inti =1; I < n; I <<=1) {E wn (cos (pi/i), f * sin (pi/i)); for(intj =0; J < N; J + = (i <<1)) {E W (1,0); for(intK =0; K < I; K++,w *= wn) {E x = a[j + k],y = w * a[j + k + i]; A[j + K] = x + y; A[j + k + i] = x-y; } } }if(f = =-1) for(inti =0; I < n; i++) a[i]/= N;} E A[MAXN],B[MAXN];intN,A[MAXN],F[MAXN];voidSolveintLintR) {if(L = = r) {F[l] = (F[l] + a[l])% P;return; }intMID = L + R >>1; Solve (L,mid); n = mid-l +1; for(inti =0; I < n; i++) A[i] = f[l + i]; m = r-l +1; for(inti =0; I < m; i++) B[i] = A[i +1]; m = n + M; L =0; for(n =1; n <= m; N <<=1) l++; for(inti =0; I < n; i++) R[i] = (r[i >>1] >>1) | ((I &1) << (L-1)); FFT (A,1); FFT (B,1); for(inti =0; I < n; i++) A[i] *= b[i]; FFT (A,-1); for(inti = mid +1; I <= R; i++) {F[i] = (F[i] + (int) Floor (A[i-l-1].R +0.5)% p)% p; } for(inti =0; I < n; i++) A[i] = b[i] =0; Solve (mid +1, r);}intMain () { while((~SCANF ("%d", &n)) && N) { for(inti =1; I <= N; i++) {A[i] = read ()% P; F[i] =0; } Solve (1, N); printf"%d\n", F[n]); }return 0;}
hdu5730 Shell Necklace "Divide and conquer FFT"