• 分零食「JSOI 2012」


    题意

    这个真的有、复杂。


    思路

    背包的思路很显然:

    (F[i][j]=sum f(k)+F[i-1][j-k])

    这个东西显然可以fft优化,但是复杂度还是过不了。

    进一步观察式子

    可以发现(F[i][j]=F[frac{i}{2}][k]*F[frac{i}{2}][j-k])

    假设(F)的前缀和为(p),那么可以推出(p[i]=p[frac{i}{2}]+p[frac{i}{2}]*dp[frac{i}{2}])

    那么像快速幂那样倍增优化即可。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
    	template<typename T>inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    
    	template<typename T>inline void write (T x) {
    		if (x<0) putchar('-'),x*=-1;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    template<typename T> struct poly {
    	T num[60000];
    };
    
    namespace Project {
    	
    	const int N=60000;
    	const double pi=acos(-1);
    	typedef complex<double> cx;
    	typedef poly<int> py;
    	
    	int n,m,p,A,o,s,u,L;
    	cx a[N],b[N];
    	int R[N];
    	py dp,g,org,tmp;
    	
    	inline void add (py &x,py y) {
    		for (register int i=0; i<=m/2; ++i) x.num[i]=(x.num[i]+y.num[i])%p;
    	}
    	inline int f (int x) {
    		return (o*x*x%p+s*x%p+u)%p;
    	}
    	inline void fft (cx *tmp,int type) {
    		for (register int i=0; i<n; ++i) if (i<R[i]) swap(tmp[i],tmp[R[i]]);
    		for (register int i=1; i<n; i<<=1) {
    			cx wn(cos(pi/i),type*sin(pi/i));
    			for (register int j=0; j<n; j+=(i<<1)) {
    				cx w(1,0);
    				for (register int k=0; k<i; ++k,w*=wn) {
    					cx s=tmp[j+k],t=tmp[j+k+i]*w;
    					tmp[j+k]=s+t,tmp[j+k+i]=s-t;
    				}
    			}
    		}
    	}
    	inline void mul (py &res,py x,py y) {
    		for (register int i=0; i<n; ++i) {
    			a[i]=x.num[i],b[i]=y.num[i];
    		}
    		fft(a,1),fft(b,1);
    		for (register int i=0; i<n; ++i) a[i]*=b[i];
    		fft(a,-1);
    		for (register int i=0; i<=m/2; ++i) {
    			res.num[i]=static_cast<int>(a[i].real()/n+0.5)%p;
    		}
    	}
    	void ksm (int l) {
    		if (l==1) return dp=g=org,void();
    		ksm(l>>1);
    		mul(tmp,dp,g),add(dp,tmp),mul(g,g,g);
    		if (l&1) {
    			mul(g,org,g),add(dp,g);
    		}
    	}
    	
    	inline void MAIN () {
    		read(n),read(p);
    		read(A),read(o),read(s),read(u);
    		m=2*n;
    		for (n=1; n<=m; n<<=1) ++L;
    		for (register int i=0; i<n; ++i) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
    		for (register int i=1; i<=m/2; ++i) org.num[i]=f(i);
    		ksm(A);
    		write(dp.num[m/2]);
    	}
    
    }
    
    int main () {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	Project::MAIN();
    }
    
  • 相关阅读:
    super与this的比较
    队列学习小结
    最左原则
    show processlist
    循环
    打印偶数
    发布模块
    eval函数
    文件
    模块
  • 原文地址:https://www.cnblogs.com/ilverene/p/11429223.html
Copyright © 2020-2023  润新知