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

HDU5730 Shell Necklace(DP + CDQ分治 + FFT)

时间:2016-09-19 19:48:55      阅读:403      评论:0      收藏:0      [点我收藏+]

标签:

题目

Source

http://acm.hdu.edu.cn/showproblem.php?pid=5730

Description

Perhaps the sea‘s definition of a shell is the pearl. However, in my view, a shell necklace with n beautiful shells contains the most sincere feeling for my best lover Arrietty, but even that is not enough.

Suppose the shell necklace is a sequence of shells (not a chain end to end). Considering i continuous shells in the shell necklace, I know that there exist different schemes to decorate the i shells together with one declaration of love.

I want to decorate all the shells with some declarations of love and decorate each shell just one time. As a problem, I want to know the total number of schemes.

Input

There are multiple test cases(no more than 20 cases and no more than 1 in extreme case), ended by 0.

For each test cases, the first line contains an integer n, meaning the number of shells in this shell necklace, where 1≤n≤105. Following line is a sequence with n non-negative integer a1,a2,…,an, and ai≤107 meaning the number of schemes to decorate i continuous shells together with a declaration of love.

Output

For each test case, print one line containing the total number of schemes module 313(Three hundred and thirteen implies the march 13th, a special and purposeful day).

Sample Input

3
1 3 7
4
2 2 2 2
0

Sample Output

14
54

 

分析

题目大概说已知连续i(1<=i<=n)个贝壳组合成一段项链的方案数a[i],求组合成包含n个贝壳的项链的总方案数。

 

  • dp[i]表示组合成包含i个贝壳的项链的总方案数
  • 转移:dp[i]=Σdp[i-j]*a[j](1<=j<=i)

 

直接枚举转移的话时间复杂度O(n2),是不行的。

其实这个转移方程是个比较特殊的卷积形式,可以用FFT去求,但是从1到n依次求的话时间复杂度是O(n2logn)。

而利用CQD分治,每次治的过程累加左半区间内各个已经求得dp值的状态对右半区间各个状态的贡献,这个贡献就是那个方程用FFT求即可,这样时间复杂度由主定理可知是O(nlog2n)。


这是个很经典的题目吧,虽然现在才做。。

 

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cmath>
  4. #include<algorithm>
  5. using namespace std;
  6. #define INF (1<<30)
  7. #define MAXN 333333
  8. const double PI=acos(-1.0);
  9. struct Complex{
  10. double real,imag;
  11. Complex(double _real,double _imag):real(_real),imag(_imag){}
  12. Complex(){}
  13. Complex operator+(const Complex &cp) const{
  14. return Complex(real+cp.real,imag+cp.imag);
  15. }
  16. Complex operator-(const Complex &cp) const{
  17. return Complex(real-cp.real,imag-cp.imag);
  18. }
  19. Complex operator*(const Complex &cp) const{
  20. return Complex(real*cp.real-imag*cp.imag,real*cp.imag+cp.real*imag);
  21. }
  22. void setValue(double _real=0,double _imag=0){
  23. real=_real; imag=_imag;
  24. }
  25. };
  26. int len;
  27. Complex wn[MAXN],wn_anti[MAXN];
  28. void FFT(Complex y[],int op){
  29. for(int i=1,j=len>>1,k; i<len-1; ++i){
  30. if(i<j) swap(y[i],y[j]);
  31. k=len>>1;
  32. while(j>=k){
  33. j-=k;
  34. k>>=1;
  35. }
  36. if(j<k) j+=k;
  37. }
  38. for(int h=2; h<=len; h<<=1){
  39. Complex Wn=(op==1?wn[h]:wn_anti[h]);
  40. for(int i=0; i<len; i+=h){
  41. Complex W(1,0);
  42. for(int j=i; j<i+(h>>1); ++j){
  43. Complex u=y[j],t=W*y[j+(h>>1)];
  44. y[j]=u+t;
  45. y[j+(h>>1)]=u-t;
  46. W=W*Wn;
  47. }
  48. }
  49. }
  50. if(op==-1){
  51. for(int i=0; i<len; ++i) y[i].real/=len;
  52. }
  53. }
  54. void Convolution(Complex A[],Complex B[],int n){
  55. for(len=1; len<(n<<1); len<<=1);
  56. for(int i=n; i<len; ++i){
  57. A[i].setValue();
  58. B[i].setValue();
  59. }
  60. FFT(A,1); FFT(B,1);
  61. for(int i=0; i<len; ++i){
  62. A[i]=A[i]*B[i];
  63. }
  64. FFT(A,-1);
  65. }
  66.  
  67. int a[111111],d[111111];
  68. Complex A[MAXN],B[MAXN];
  69.  
  70. void cdq(int l,int r){
  71. if(l==r){
  72. d[l]+=a[l];
  73. d[l]%=313;
  74. return;
  75. }
  76. int mid=l+r>>1;
  77. cdq(l,mid);
  78.  
  79. for(int i=l; i<=mid; ++i) A[i-l].setValue(d[i]);
  80. for(int i=0; i<=r-l; ++i) B[i].setValue(a[i]);
  81. for(int i=mid-l+1; i<=r-l; ++i) A[i].setValue();
  82. Convolution(A,B,r-l+1);
  83. for(int i=mid+1; i<=r; ++i){
  84. d[i]+=((long long)(A[i-l].real+0.5))%313;
  85. d[i]%=313;
  86. }
  87. cdq(mid+1,r);
  88. }
  89.  
  90. int main(){
  91. for(int i=0; i<MAXN; ++i){
  92. wn[i].setValue(cos(2.0*PI/i),sin(2.0*PI/i));
  93. wn_anti[i].setValue(wn[i].real,-wn[i].imag);
  94. }
  95. int n;
  96. while(~scanf("%d",&n) && n){
  97. for(int i=1; i<=n; ++i){
  98. scanf("%d",a+i);
  99. a[i]%=313;
  100. }
  101. memset(d,0,sizeof(d));
  102. cdq(1,n);
  103. printf("%d\n",d[n]);
  104. }
  105. return 0;
  106. }

 

HDU5730 Shell Necklace(DP + CDQ分治 + FFT)

标签:

原文地址:http://www.cnblogs.com/WABoss/p/5886232.html

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