zoukankan      html  css  js  c++  java
  • HDU5730 Shell Necklace (CDQ+FFT/NTT)

    HDU-5730(CDQ+FFT/NTT)

    题意:将长度为\(n\)的序列分成若干段,每段\([l,r]\)的权值为\(a_{r-l+1}\),一种分法的权值为所有段的乘积,求所有可能的分法的权值和

    根据题意可以得到简单\(dp\)

    \(dp_0=1,dp_i=\sum_0^{i-1}dp_j \cdot a_{i-j}\)

    可以看到是一个\(i-j\)形式的作差卷积

    但是直接卷积我们无法保证先求出了\(dp_j\),所有可以用\(CDQ\)分治优化,复杂度\(n\log^2 n\)

    具体实现见代码

    #include<bits/stdc++.h>
    using namespace std;
    
    #define reg register
    typedef long long ll;
    #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
    
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); } 
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); } 
    
    char IO;
    int rd(){
    	int s=0,f=0;
    	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const double PI=acos(-1);
    
    const int N=(1<<18)+4,P=313;
    
    int n;
    int a[N],dp[N];
    struct Cp{
    	double x,y;
    	Cp operator + (const Cp t) const { return (Cp){x+t.x,y+t.y}; }
    	Cp operator - (const Cp t) const { return (Cp){x-t.x,y-t.y}; }
    	Cp operator * (const Cp t) const { return (Cp){x*t.x-y*t.y,x*t.y+y*t.x}; }
    } A[N],B[N];
    
    Cp w[N];
    int rev[N];
    void FFT(int n,Cp *a,Cp *w){
    	rep(i,1,n-1) if(rev[i]>i) swap(a[i],a[rev[i]]);
    	for(reg int i=1;i<n;i<<=1) {
    		int len=i*2;
    		for(reg int l=0;l<n;l+=len) {
    			for(reg int j=l;j<l+i;++j) {
    				Cp t=a[j+i]*w[n/len*(j-l)];
    				a[j+i]=a[j]-t;
    				a[j]=a[j]+t;
    			}
    		}
    	}
    }
    
    void Solve(int l,int r){ 
    	if(l==r) return;
    	int mid=(l+r)>>1;
    	Solve(l,mid); //先求出左边所有的
        
    	int R=1,c=-1;
    	while(R<=r-l+1) R<<=1,c++;
    	rep(i,1,R) rev[i]=(rev[i>>1]>>1)|((i&1)<<c);
    	w[0]=(Cp){1,0};
    	w[1]=(Cp){cos(2*PI/R),sin(2*PI/R)};
    	rep(i,2,R) w[i]=w[i-1]*w[1];
    	rep(i,l,mid) A[i-l]=(Cp){1.0*dp[i],0};
    	rep(i,1,r-l+1) B[i]=(Cp){1.0*a[i],0};
    	FFT(R,A,w),FFT(R,B,w);
    	rep(i,0,R) w[i].y=-w[i].y,A[i]=A[i]*B[i];
    	FFT(R,A,w);
    	rep(i,mid+1,r) dp[i]=(dp[i]+ll(A[i-l].x/R+0.5))%P;
    	rep(i,0,R) A[i].x=A[i].y=B[i].x=B[i].y=0;
        //让左边已经求出来的向右边转移
        
    	Solve(mid+1,r);
        //让右边之间转移
    }
    
    int main(){
    	while(~scanf("%d",&n) && n) {
    		rep(i,1,n) a[i]=rd()%P,dp[i]=0;
    		dp[0]=1;
    		Solve(0,n);
    		printf("%d\n",dp[n]);
    	}
    }
    
    
    
    
    
  • 相关阅读:
    H3C-U200无法通过公网访问内网服务器
    mtr工具
    nginx网页跳转失败-302
    http协议
    接口 Swagger 部分Web API的隐藏
    接口 ApiController调用Controller 模拟Session 封装
    接口 Swagger 03 基于Token的身份认证
    电商 批量修改图片分辨率
    接口 Swagger 01 让Asp.net MVC项目显示API文档
    接口 Swagger 02 显示代码注释
  • 原文地址:https://www.cnblogs.com/chasedeath/p/12101353.html
Copyright © 2011-2022 走看看