HDU - 5730 Shell Necklace

不难想到DP方程f[i]=sigema(0,i-1)j f[j]*a[i-j]

这是一个卷积,然而并不能直接卷

上分治fft

注意ntt用不了。。。313=2^3*3*13+1

推的我心态都崩了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
typedef long double LD;
const int _=1e2;
const int maxn=1e5+_;
const int fbin=((1<<17)<<1)+_;
const int mod=313;

const double pi=acos(-1.0);
struct complex
{
    LD r,i;
    complex(){} complex(double R,double I){r=R,i=I;}
    friend complex operator +(complex c1,complex c2){return complex(c1.r+c2.r,c1.i+c2.i);}
    friend complex operator -(complex c1,complex c2){return complex(c1.r-c2.r,c1.i-c2.i);}
    friend complex operator *(complex c1,complex c2){return complex(c1.r*c2.r-c1.i*c2.i,c1.r*c2.i+c2.r*c1.i);}
}A[fbin],B[fbin]; int Re[fbin],h[fbin];
void FFT(complex *a,int n,int op)
{
    for(int i=0;i<n;i++)
        if(i<Re[i])swap(a[i],a[Re[i]]);
     
    for(int i=1;i<n;i<<=1)
    {
        complex wn(cos(pi/i),sin(op*pi/i));
        for(int j=0;j<n;j+=(i<<1))
        {
            complex w(1,0);
            for(int k=0;k<i;k++,w=w*wn)
            {
                complex t1=a[j+k],t2=a[j+k+i];
                a[j+k]=t1+w*t2;
                a[j+k+i]=t1-w*t2;
            }
        }
    }
    if(op==-1)
        for(int i=0;i<n;i++)
            h[i]=(LL)(A[i].r/n+0.5)%mod,a[i].i=0;
}

int a[maxn],f[maxn];
void solve(int l1,int r1,int l2,int r2)
{
    int d1=(r1-l1+1),d2=(r2-l2+1);
    
    int n,m,L;
    m=d1+d2-1;for(n=1,L=0;n<m;n*=2,L++);
    for(int i=0;i<n;i++)Re[i]=(Re[i>>1]>>1)|((i&1)<<(L-1));
    for(int i=0;i<n;i++)A[i].r=A[i].i=B[i].r=B[i].i=0;
    
    for(int i=0;i<d1;i++)A[i].r=f[i+l1];
    for(int i=0;i<d2;i++)B[i].r=a[i+l2];
    FFT(A,n,1),FFT(B,n,1);
    for(int i=0;i<n;i++)A[i]=A[i]*B[i];
    FFT(A,n,-1);
}

void cdq(int l,int r)
{
    if(l==r)return ;
    int mid=(l+r)/2;
    cdq(l,mid);
    solve(l,mid,1,r-l);
    for(int i=mid+1,j=mid-l;i<=r;i++,j++)
        f[i]=(f[i]+h[j])%mod;
    cdq(mid+1,r);
}

int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)break;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]%=mod;
        memset(f,0,sizeof(f));
        f[0]=1;
        cdq(0,n);
//        for(int i=1;i<n;i++)printf("%d ",f[i]);
        printf("%d\n",f[n]);
    }
    
    return 0;
}

 

posted @ 2019-03-19 07:18  AKCqhzdy  阅读(98)  评论(0编辑  收藏  举报