分零食「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();
}
原文地址:https://www.cnblogs.com/ilverene/p/11429223.html