• HDU 5730 Shell Necklace cdq分治+FFT


    题意:一段长为 i 的项链有 a[i] 种装饰方式,问长度为n的相连共有多少种装饰方式

    分析:采用dp做法,dp[i]=∑dp[j]*a[i-j]+a[i],(1<=j<=i-1)

    然后对于这种递推式,也就是dp[i]等于前j个dp数组和a数组的卷积,然后可看所有的

    一看n是1e5,所以暴力超时,然后采用cdq分治加速,这种卷积递推通常采用cdq分治加速

     cdq的话很简单了,就是先递归左边,算左对右的贡献,递归右边就行,一半一半更新

    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N = 1e5+5;
    const int mod = 313;
    typedef long long LL;
    const double pi = acos(-1.0);
    int a[N],dp[N],n;
    struct complex{
      double r,i;
      complex(double R=0,double I=0){
        r=R;i=I;
      }
      complex operator+(const complex &a)const{
        return complex(r+a.r,i+a.i);
      }
      complex operator-(const complex &a)const{
        return complex(r-a.r,i-a.i);
      }
      complex operator*(const complex &a)const{
        return complex(r*a.r-i*a.i,r*a.i+i*a.r);
      }
    }x[N*4],y[N*4];
    void change(complex x[],int len){
       int i,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>>=1;}
         if(j<k)j+=k;
       }
    }
    void fft(complex x[],int len,int on){
       change(x,len);
       for(int i=2;i<=len;i<<=1){
        complex wn(cos(-on*2*pi/i),sin(-on*2*pi/i));
        for(int j=0;j<len;j+=i){
          complex w(1,0);
          for(int k=j;k<j+i/2;++k){
              complex u = x[k];
              complex t = w*x[k+i/2];
              x[k]=u+t;
              x[k+i/2]=u-t;
              w=w*wn;
          }
        }
       }
       if(on==-1)for(int i=0;i<len;++i)x[i].r/=len;
    }
    void up(int &x){
      x%=mod;
    }
    void cdq(int l,int r){
      if(l==r){dp[l]+=a[l];up(dp[l]);return;}
      int mid=l+r>>1;
      cdq(l,mid);
      int len=1;
      while(len<=(r-l+1))len<<=1;
      for(int i=0;i<len;++i)x[i]=y[i]=complex(0,0);
      for(int i=l;i<=mid;++i)x[i-l]=complex(dp[i],0);
      for(int i=1;i<=r-l+1;++i)y[i-1]=complex(a[i],0);
      fft(x,len,1);fft(y,len,1);
      for(int i=0;i<len;++i)x[i]=x[i]*y[i];
      fft(x,len,-1);
      for(int i=mid+1;i<=r;++i)
        dp[i]+=(int)(x[i-l-1].r+0.5),up(dp[i]);
      cdq(mid+1,r);
    }
    int main(){
        while(~scanf("%d",&n),n){
           for(int i=1;i<=n;++i){
            scanf("%d",&a[i]);up(a[i]);dp[i]=0;
           }
           cdq(1,n);
           printf("%d
    ",dp[n]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【LeetCode每天一题】Pascal's Triangle(杨辉三角)
    【Redis】持久化
    【LeetCode每天一题】Swap Nodes in Pairs
    【LeetCode每天一题】Reverse String
    [bzoj2152]聪聪可可
    [bzoj3572][Hnoi2014]世界树
    Codeforces Round#409/VK-Cup 2017 Round2
    Educational Codeforces Round#19
    [bzoj4813][Cqoi2017]小Q的棋盘
    [bzoj4236]JOIOJI
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5705514.html
Copyright © 2020-2023  润新知