• BZOJ #3177. [Coci2012]Skakac


    一道比较繁琐的DP题,细节比较多,写了半小时调了一小时……

    首先容易想到我们分开求骑士的位置和格子的通行情况,然后合并起来即可

    前者比较容易,(O(n^2 imes t))的暴力DP很好想,然后在此基础上把一行状压起来就可以做到(O(n imes t))

    考虑如何处理某一时刻格子的通行情况,在涉及到倍数/因数的问题时,我们常常考虑按(sqrt n)阈值

    首先当(a_{i,j}ge1000)时,它存在的时刻数显然(le1000),那么可以直接暴力维护

    考虑当(a_{i,j}<1000)时,我们可以考虑把在范围内的质数全部搞出来,设计状态(g_{i,j,k})表示第(k)行整除(p_i^j)的关系(其中(p_i)表示第(i)个质数)

    然后显然当(t=p_1^{c_1} imes p_2^{c_2} imescdots imes p_m^{c_m})可以从所有的(p_1^{c_1'} imes p_2^{c_2'} imescdots imes p_m^{c_m'}(c_1'le c_1,c_2'le c_2,cdots,c_m'le c_m))的状态转移来

    然后我们给时刻分解质因数,将预处理好的(g)修改上去即可,然后我们注意到一段质数中间会出现一些次数为(0)的空隙,我们预处理下所有空隙的状态即可

    总体复杂度(O(n imes tlog t)),足以通过此题

    #include<cstdio>
    #include<algorithm>
    #define RI register int
    #define CI const int&
    using namespace std;
    const int N=35,M=500,S=1e6;
    struct element
    {
    	int t,x,y;
    	inline element(CI T=0,CI X=0,CI Y=0) { t=T; x=X; y=Y; }
    	friend bool operator < (const element& A,const element& B)
    	{
    		return A.t<B.t;
    	}
    }a[N*N*1000],fc[M]; bool vis[S+5]; int n,t,sx,sy,tot,x,ansx[N*N],ansy[N*N],pt;
    int f[2][N],g[500][N][N],sum[500][500][N],c[N],prime[S+5],cnt,num,d[S+5];
    #define P(x) prime[x]
    inline void init(CI n=S)
    {
    	RI i,j; for (i=2;i<=n;++i)
    	{
    		if (!vis[i]) P(++cnt)=i,d[i]=cnt;
    		for (j=1;j<=cnt&&i*P(j)<=n;++j)
    		{
    			vis[i*P(j)]=1; d[i*P(j)]=j;
    			if (i%P(j)==0) break;
    		}
    	}
    	for (i=1;i<=cnt;++i) if (P(i)<=1000) num=i; else break;
    }
    inline void add1(int v,CI x,CI y)
    {
    	for (RI i=1;i<=num;++i)
    	{
    		int c=0; while (v%P(i)==0) ++c,v/=P(i);
    		for (;c<=20;++c) g[i][c][x]|=(1<<y);
    	}
    }
    inline void add2(CI v,CI x,CI y)
    {
    	for (RI i=1;i*v<=t;++i) a[++tot]=element(i*v,x,y);
    }
    inline void DP_sum(void)
    {
    	for (RI i=1,j,k,l;i<=num;++i) for (j=i;j<=num;++j) for (l=1;l<=n;++l)
    	for (sum[i][j][l]=(1<<n+1)-1,k=i;k<=j;++k) sum[i][j][l]&=g[k][0][l];
    }
    inline void resolve(int x)
    {
    	RI i,j; for (pt=0;x!=1;)
    	{
    		int ct=0,t=d[x]; while (x%P(t)==0) x/=P(t),++ct;
    		fc[++pt]=element(t,ct);
    	}
    	int lst=1; for (sort(fc+1,fc+pt+1),i=1;i<=pt&&fc[i].t<=num;++i)
    	{
    		for (j=1;j<=n;++j) c[j]&=g[fc[i].t][fc[i].x][j];
    		if (lst<fc[i].t) for (j=1;j<=n;++j) c[j]&=sum[lst][fc[i].t-1][j]; lst=fc[i].t+1;
    	}
    	if (lst<num) for (j=1;j<=n;++j) c[j]&=sum[lst][num][j];
    }
    #undef P
    int main()
    {
    	RI i,j,cur; for (scanf("%d%d%d%d",&n,&t,&sx,&sy),init(),i=1;i<=n;++i)
    	for (j=1;j<=n;++j) if (scanf("%d",&x),x<1000) add1(x,i,j); else add2(x,i,j);
    	/*for (cur=1;cur<=4;++cur) for (i=1;i<=n;++i) for (j=1;j<=n;++j)
    	printf("%d ",g[cur][i][j]); putchar('
    ');*/
    	for (DP_sum(),sort(a+1,a+tot+1),i=cur=1,f[0][sx]|=(1<<sy);i<=t;++i)
    	{
    		int nw=i&1; for (j=1;j<=n;++j) f[nw][j]=0,c[j]=(1<<n+1)-1;
    		for (j=1;j<=n;++j)
    		{
    			if (j>2) f[nw][j]|=(f[nw^1][j-2]>>1)|(f[nw^1][j-2]<<1);
    			if (j+2<=n) f[nw][j]|=(f[nw^1][j+2]>>1)|(f[nw^1][j+2]<<1);
    			if (j>1) f[nw][j]|=(f[nw^1][j-1]>>2)|(f[nw^1][j-1]<<2);
    			if (j+1<=n) f[nw][j]|=(f[nw^1][j+1]>>2)|(f[nw^1][j+1]<<2);
    		}
    		/*RI k; for (printf("%d
    ",i),j=1;j<=n;++j) for (k=1;k<=n;++k)
    		printf("%d%c",(f[nw][j]>>k)&1," 
    "[k==n]); putchar('
    ');*/
    		for (resolve(i);cur<=tot&&a[cur].t==i;++cur) c[a[cur].x]|=(1<<a[cur].y);
    		/*for (j=1;j<=n;++j) for (k=1;k<=n;++k)
    		printf("%d%c",(c[j]>>k)&1," 
    "[k==n]); putchar('
    ');*/
    		for (j=1;j<=n;++j) f[nw][j]&=c[j];
    		/*for (j=1;j<=n;++j) for (k=1;k<=n;++k)
    		printf("%d%c",(f[nw][j]>>k)&1," 
    "[k==n]); putchar('
    ');*/
    	}
    	/*for (cur=1;cur<=4;++cur) for (i=1;i<=4;++i) for (j=1;j<=n;++j)
    	printf("%d ",sum[cur][i][j]); putchar('
    ');*/
    	for (pt=0,i=1;i<=n;++i) for (j=1;j<=n;++j) if ((f[t&1][i]>>j)&1)
    	ansx[++pt]=i,ansy[pt]=j; for (printf("%d
    ",pt),i=1;i<=pt;++i)
    	printf("%d %d
    ",ansx[i],ansy[i]); return 0;
    }
    
  • 相关阅读:
    python学习笔记(2)--sublimeText3运行python
    python学习笔记(1)--遍历txt文件,正则匹配替换文字
    JS学习笔记(4)--js变量的生命周期
    JS学习笔记(3)--json格式数据的添加,删除及排序方法
    JS学习笔记(2)--正则表达式获取指定字符串
    JS学习笔记(1)--sort排序
    VBA学习笔记(1)----VBA对象属性方法
    能够作图的软件都有哪些
    怎么用ChemDraw连接两个结构片段
    在几何画板上画椭圆可以根据椭圆第二定义
  • 原文地址:https://www.cnblogs.com/cjjsb/p/13362547.html
Copyright © 2020-2023  润新知