• 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
  • 相关阅读:
    [Java]基础知识复习:例外的在继承中的机制
    2005年7月28日,终于结束了。
    从不知道到知道,从没有到有,是一个质的进步。
    正确的心态、积极的态度、坚定的信心、愉快的心情
    今天终于见到了她。
    textarea自增高(无滚动条)纯js实现
    带,号字符串转成表的函数操作
    MAK密钥集锦
    用户注册信息验证类库
    C#将文档(Word\ Excel\ PowerPoint\ Visio\ text\ XML\ RTF\ CSV )转成Pdf
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5705514.html
Copyright © 2020-2023  润新知