• HDU5730 Shell Necklace


    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:HDU5730

    正解:分治$FFT$

    解题报告:

      分治$+FFT$模板题。

      容易发现一个$O(n^2)$的$DP$方程,就是一个卷积的形式,在分治过程中,用左边更新右边,做一次$FFT$。

      注意不要每次清空数组就好了。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <complex>
    #include <cmath>
    #include <cstring>
    using namespace std;
    typedef long long LL;
    typedef complex<double> C;
    const int MAXN = 400011;
    const int mod = 313;
    const double pi = acos(-1);
    int n,R[MAXN],L;
    LL Out[MAXN],tmp[MAXN],a[MAXN];
    C c[MAXN],d[MAXN];
    
    inline void FFT(C *a,int n,int f){
    	for(int i=0;i<n;i++) if(i<R[i]) swap(a[i],a[R[i]]);
    	for(int i=1;i<n;i<<=1) {
    		C wn(cos(pi/i),sin(f*pi/i)),x,t;
    		for(int j=0;j<n;j+=(i<<1)) {
    			C w(1,0);
    			for(int k=0;k<i;k++,w*=wn) {
    				x=a[j+k]; t=a[j+k+i]*w;
    				a[j+k]=x+t;
    				a[j+k+i]=x-t;
    			}
    		}
    	}
    }
    
    inline void calc(LL *aa,int len1,LL *bb,int len2){
    	int ll=len1+len2; int len=1; L=0;
    	for(;len<=ll;len<<=1) L++; R[0]=0;
    	for(int i=0;i<len;i++) R[i]=(R[i>>1]>>1) | ((i&1) << (L-1));
    
    	for(int i=0;i<len1;i++) c[i]=0,c[i]=aa[i];
    	for(int i=len1;i<=len;i++) c[i]=0;
    	for(int i=0;i<len2;i++) d[i]=0,d[i]=bb[i];
    	for(int i=len2;i<=len;i++) d[i]=0;	
    	
    	FFT(c,len,1); FFT(d,len,1);
    	
    	for(int i=0;i<=len;i++) c[i]*=d[i];
    	
    	FFT(c,len,-1);
    	
    	for(int i=0;i<=len1+len2;i++) tmp[i]=(LL)(c[i].real()/len+0.5);
    }
    
    inline void fft(int l,int r){
    	int mid=(l+r)>>1; calc(Out+l,mid-l+1,a,r-l+1);
    	for(int i=mid-l+1;i<=r-l;i++) Out[l+i]+=tmp[i],Out[l+i]%=mod;
    }
    
    inline void CDQ(int l,int r){
    	if(l==r) return ;
    	int mid=(l+r)>>1;
    	CDQ(l,mid);
    	fft(l,r);
    	CDQ(mid+1,r);
    }
    
    inline void work(){
    	while(1) {
    		scanf("%d",&n); if(n==0) break;
    		for(int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]%=mod;
    		memset(Out,0,sizeof(Out));
    		Out[0]=1;
    		CDQ(0,n);
    		Out[n]+=mod;
    		Out[n]%=mod;
    	
    		printf("%lld
    ",Out[n]);
    	}
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    

      

  • 相关阅读:
    Java版AES-CBC-CMAC加密
    并发编程(十九):并发编程实践
    并发编程(十八):ScheduledThreadPoolExcutor和FutureTask
    并发编程(十七):Excutor与ThreadPoolExcutor
    并发编程(十六):线程池概述
    并发编程(十五):Java并发工具类
    并发编程(十四):原子操作类
    并发编程(十三):Fork-Join框架
    并发编程(十二):阻塞队列
    并发编程(十一):非阻塞队列ConcurrentLinkedQueue
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6866774.html
Copyright © 2020-2023  润新知