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]随机数的主要内容,如果未能解决你的问题,请参考以下文章