bzoj3557: [Ctsc2014]随机数

Posted f321dd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3557: [Ctsc2014]随机数相关的知识,希望对你有一定的参考价值。

常数优化数次后终于卡过去了,感人肺腑。成功get rank last。

orz出题人clj:

http://download.noi.cn/T/2014/CCF_CTSC2014.rar 解压密码CCfCtsC2014

orz神犇们的题解以及常数优化技巧:

http://blog.miskcoo.com/2015/05/bzoj-3557

http://cjjlsdy.blog.163.com/blog/static/180370563201461133026/

http://picks.logdown.com/posts/197310-solution-to-ctsc2014-random

http://vfleaking.blog.163.com/blog/static/1748076342014421105221134/

顺便吐槽一句对拍的时候发现这几份代码输出不一样。

简要说一下做法:

每个数可以看做GF(2)下的多项式,则mk=m0*x^k (mod x^m+X)。

需要多项式取模,blog.miskcoo.com及picks.logdown.com里有讲解。

那么第一问FFT+快速幂,第二问由于x是好的,则x是mod x^m+X意义下的群的生成元,那么x=x^2^m,多项式a的逆元即为a^(2^m-2),求个逆元即可。

为优化常数可以在n较小时用压位乘法而不用FFT(orz vfk)

#include<bits/stdc++.h>
#define N (1<<21)
using namespace std;
struct vec{
	double x,y;
	vec(double x=0,double y=0)
	:x(x),y(y){}
};
vec operator+(vec a,vec b){
	return vec(
	a.x+b.x,a.y+b.y);
}
vec operator-(vec a,vec b){
	return vec(
	a.x-b.x,a.y-b.y);
}
vec operator*(vec a,vec b){
	return vec(
	a.x*b.x-a.y*b.y,
	a.x*b.y+a.y*b.x);
}
void fft(vec* q,int n,int m){
	int i,j,k;
	for(i=j=0;i!=n;++i){
		if(i<j)
			swap(q[i],q[j]);
		for(k=n>>1;
		(j^=k)<k;k>>=1);
	}
	for(i=2;i<=n;i<<=1){
		double a(2*m
		*acos(-1)/i);
		vec s(cos(a),sin(a));
		for(j=0;j!=n;j+=i){
			vec t=1;
			for(k=j;k!=j+i/2;
			t=t*s,++k){
				vec u=q[k];
				vec v=t*q[k+i/2];
				q[k]=u+v;
				q[k+i/2]=u-v;
			}
		}
	}
	if(!~m)
		for(i=0;i!=n;++i)
			q[i].x/=n;
}
int* mem(int k){
	return (int*)calloc(k,4);
}
struct pol{
	int k,*u;
	pol(int v=0,int s=N)
	:k(1),u(mem(s)){u[0]=v;}
	~pol(){free(u);}
	int& operator[](int i){
		return u[i];
	}
	pol& operator=(int v){
		k=1,u[0]=v;
		return *this;
	}
	pol& operator=(pol& v){
		memcpy(u,v.u,(k=v.k)*4);
		return *this;
	}
	pol& operator+=(pol& v);
	pol& operator*=(pol& v);
};
int get(int k){
	int i=1;
	for(;i<k;i<<=1);
	return i;
}
pol& pol::operator+=(pol& v){
	for(int i=0;i!=k;++i)
		u[i]=u[i]+v[i]&1;
	return *this;
}
pol& pol::operator*=(pol& v){
	if(!k||!v.k)
		return *this=0;
	int i,j,n=k,m=v.k;
	k+=m-1;
	if(k<=1e4){
		typedef unsigned
		long long ds[200];
		static ds s,t;
		int q=k+63>>6;
		fill(s,s+q,0);
		fill(t,t+q,0);
		for(i=0;i!=m;++i)
			s[i>>6]|=0ull
			+v[i]<<(i&63);
		for(i=0;i!=n;++i){
			if(u[i])
				for(j=0;j!=q;++j)
					t[j]^=s[j];
			for(j=q-1;j;--j)
				s[j]=s[j]<<1
				|s[j-1]>>63&1;
			s[0]<<=1;
		}
		for(i=0;i!=k;++i)
			u[i]=t[i>>6]>>(i&63)&1;
	}else{
		static vec s[N],t[N];
		j=get(k);
		copy(u,u+n,s);
		copy(v.u,v.u+m,t);
		fill(s+n,s+j,0);
		fill(t+m,t+j,0);
		fft(s,j,1);
		fft(t,j,1);
		for(i=0;i!=j;++i)
			s[i]=s[i]*t[i];
		fft(s,j,-1);
		for(i=0;i!=k;++i)
			u[i]=int(s[i].x+.5)&1;
	}
	return *this;
}
void mov(pol& a,int k){
	if(a.k<k)
		fill(a.u+a.k,a.u+k,0);
	a.k=k;
}
void inv(pol& u,pol& v,int k){
	if(k<=1)v=k;
	else{
		int m=k+1>>1;
		inv(u,v,m);
		mov(v*=v,k);
		mov(v*=u,k);
	}
}
int fix(pol& a){
	while(a.k&&!a[a.k-1])
		--a.k;
	return a.k;
}
void rev(pol& u,pol& v,int k){
	reverse_copy(
	u.u,u.u+u.k,v.u);
	v.k=u.k,mov(v,k);
}
void print(pol& a,
const char* s=""){
	printf("%s",s);
	for(int i=0;i!=a.k;++i)
		printf("%d ",a[i]);
	putchar(10);
}
void div(pol& a,pol& b,pol& d,pol& r){
	if(fix(a)<fix(b))
		d=0,r=a;
	else{
		static pol u,v;
		int k=a.k-b.k+1;
		rev(a,d,k);
		rev(b,u,k);
		inv(u,v,k);
		mov(d*=v,k);
		reverse(d.u,d.u+k);
		r=b,r*=d;
		mov(r,b.k-1),r+=a;
	}
}
void gcd(pol& a,pol& b,pol& x,pol& y){
	if(!fix(b))
		x=1,y=0;
	else{
		pol u(0,1<<11);
		pol v(0,1<<11);
		div(a,b,u,v);
		gcd(b,v,y,x);
		u*=x,mov(y,max(
		y.k,u.k)),y+=u;
	}
}
void mul(pol& a,pol& b,pol& p){
	if(!a.k||!b.k){
		a=0;return;
	}
	int i,j,k=a.k+b.k-1;
	if(k<p.k){
		a*=b;return;
	}
	if(k<=1e4){
		typedef unsigned
		long long ds[200];
		static ds s,t,u;
		int q=k+63>>6;
		fill(s,s+q,0);
		fill(t,t+q,0);
		for(i=0;i!=b.k;++i)
			s[i>>6]|=0ull
			+b[i]<<(i&63);
		for(i=0;i!=p.k;++i)
			u[i>>6]|=0ull
			+p[i]<<(i&63);
		for(i=0;i!=a.k;++i){
			if(a[i])
				for(j=0;j!=q;++j)
					t[j]^=s[j];
			for(j=q-1;j;--j)
				s[j]=s[j]<<1
				|s[j-1]>>63&1;
			s[0]<<=1;
			if(s[(p.k+63>>6)-1]
			>>(p.k-1&63)&1)
				for(j=0;j!=q;++j)
					s[j]^=u[j];
		}
		a.k=p.k-1;
		for(i=0;i!=a.k;++i)
			a[i]=t[i>>6]>>(i&63)&1;
	}else{
		static pol u,v;
		u=a;
		div(u*=b,p,v,a);
	}
}
void inv(pol& a,int m,pol& p){
	static pol u;
	u=a,a=1;
	while(--m){
		mul(u,u,p);
		mul(a,u,p);
	}
}
template<class T>
inline void scan(T& x){
	static int u;
	x=0;
	while((u=getchar())<48);
	do
		x=x*10+u-48;
	while((u=getchar())>32);
}
int main(){
	pol a,m0,u,v,x;
	int i,m,l,q;
	long long k;
	scan(m);
	for(i=0;i!=m;++i)
		scan(x[i]);
	for(i=0;i!=m;++i)
		scan(m0[i]);
	x.k=m0.k=m;
	x[x.k++]=1;
	if(scan(q),q){
		scan(l);
		for(i=0;i!=m;++i)
			scan(a[i]);
		a.k=m;
		inv(u=m0,m,x);
		mul(a,u,x);
		for(i=0;i!=m-l;++i)
			mul(a,a,x);
	}else{
		a=u[1]=1,u.k=2;
		scan(k);
		for(;k;k>>=1){
			if(k&1)
				mul(a,u,x);
			if(k>>1)
				mul(u,u,x);
		}
	}
	mul(m0,a,x);
	for(i=0;i!=m;++i)
		putchar(m0[i]+48);
	putchar(10);
}

  

以上是关于bzoj3557: [Ctsc2014]随机数的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3555: [Ctsc2014]企鹅QQ

bzoj——3555: [Ctsc2014]企鹅QQ

BZOJ-3555: [Ctsc2014]企鹅QQ (hash)

Bzoj 3555: [Ctsc2014]企鹅QQ

BZOJ_3555_[Ctsc2014]企鹅QQ_哈希

Bzoj3555: [Ctsc2014]企鹅QQ