题意:
给出连续的1-n个珠子的涂色方法 a[i](1<=i<=n), 问长度为n的珠链共有多少种涂色方案
分析:
可以得到DP方程: DP[n] = ∑(i=1,n) (DP[n-i]*a[i]).
该方程为卷积形式,故 CDQ + FFT
CDQ: 将 [l,r] 二分, 先得到[l,mid]的答案,再更新[l,mid]对[mid+1,r]的贡献.
对任意 DP[j](mid+1 <= j <= r), [l,mid] 对其贡献为 ∑(i=l,mid) (DP[i]*a[j - i]) , 即多项式 DP 与 a 相乘后次数为j项.
FFT: 优化多项式相乘.
(1 和 l 看不清的也就这破博客园了,代码还是粘下来的好,= =)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 const double PI = 4 * atan(1.0); 7 const int MAXN = 200005; 8 const int MOD = 313; 9 struct Complex 10 { 11 double x, y; 12 Complex(double xx = 0.0, double yy = 0.0) : x(xx), y(yy) {} 13 Complex operator - (const Complex &b) const 14 { 15 return Complex(x - b.x, y - b.y); 16 } 17 Complex operator + (const Complex &b) const 18 { 19 return Complex(x + b.x, y + b.y); 20 } 21 Complex operator * (const Complex &b) const 22 { 23 return Complex(x*b.x - y*b.y, x*b.y + y*b.x); 24 } 25 }; 26 void Change(Complex y[], int len) 27 { 28 int i, j, k; 29 for (i = 1, j = len/2; i < len-1; i++) 30 { 31 if (i < j) swap(y[i], y[j]); 32 k = len / 2; 33 while (j >= k) 34 { 35 j -= k; 36 k /= 2; 37 } 38 if (j < k) j += k; 39 } 40 } 41 void FFT(Complex y[], int len,int on) 42 { 43 Change(y, len); 44 for (int h = 2; h <= len; h <<= 1) 45 { 46 Complex wn( cos(-on*2*PI/h), sin(-on*2*PI/h) ); 47 for (int j = 0; j < len; j +=h) 48 { 49 Complex w(1, 0); 50 for (int k = j; k < j + h/2; k++) 51 { 52 Complex u = y[k]; 53 Complex t = w * y[k + h/2]; 54 y[k] = u + t; 55 y[k + h/2] = u - t; 56 w = w * wn; 57 } 58 } 59 } 60 if (on == -1) 61 for (int i = 0; i < len; i++) 62 y[i].x /= len; 63 } 64 int t, n; 65 Complex x[MAXN], y[MAXN]; 66 int a[MAXN/2], dp[MAXN/2]; 67 void CDQ(int l, int r) 68 { 69 if (l == r) { dp[l] = (dp[l] + a[l]) % MOD; return; } 70 int mid = (l + r) >> 1; 71 CDQ(l, mid);//处理前半段 72 int len = 1, len1 = mid - l + 1, len2 = r - l + 1; 73 while(len < len2) len <<= 1; 74 for (int i = 0; i < len1; i++) x[i] = Complex(dp[i + l], 0); 75 for (int i = len1; i < len; i++) x[i] = Complex(0, 0); 76 for (int i = 0; i < len2; i++) y[i] = Complex(a[i], 0); 77 for (int i = len2; i < len; i++) y[i] = Complex(0, 0); 78 FFT(x, len, 1); 79 FFT(y, len, 1); 80 for (int i = 0; i < len; i++) x[i] = x[i] *y[i]; 81 FFT(x, len, -1); 82 for (int i = mid+1; i <= r; i++)//更新贡献 83 { 84 dp[i] = (int)(dp[i] + x[i - l].x + 0.5) %MOD; 85 } 86 CDQ(mid + 1, r);//处理后半段 87 } 88 int main() 89 { 90 while(~scanf("%d",&n) && n) 91 { 92 for (int i = 1; i <= n; i++) 93 { 94 scanf("%d",&a[i]); 95 a[i] %= MOD; 96 dp[i] = 0; 97 } 98 CDQ(1, n); 99 printf("%d ", dp[n]); 100 } 101 }