码迷,mamicode.com
首页 > 系统相关 > 详细

HDU 5730 - Shell Necklace

时间:2016-08-03 23:55:40      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:

题意:

  给出连续的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\n", dp[n]);
100     }
101 }

 

HDU 5730 - Shell Necklace

标签:

原文地址:http://www.cnblogs.com/nicetomeetu/p/5734820.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!