被标解虐飞了QAQ。。虽然我不知道为什么..
但还是蛮开心的,因为之前有过一个想法,就是要尽量做到做题时就算有结论没有猜出,或者想歪了,也能用一个哪怕复杂一点的方法做出来
昨天晚上写了好像从八点多写到了十点。。
感觉细节很多。。写得很慢,感觉写得很稳,把能稳的都写稳了。。
于是昨晚成功在回宿舍前被卡常。。
今天早上怒卡了一波常数才过。。
这里提供一个不一定是正解的做法吧。。因为看起来实在和别人差蛮多的。。
首先,我们可以用数学知识算出来他最后在哪一个点
也就是算一下他往上走了多少步,往下走了多少步,往左走了多少步,往右走了步,然后加加减减就可以了。。
然后我们考虑倒着走回去,那么这个时候,如果一个点如果之前被走过了,那么他是肯定不会被染色的,对吧
所以我们每一次就只选择没有走过的点,直接跳过去
这个功能可以对于每一个点用四个并查集来维护,分别是向上,向下,向左,向右,下一个没有染过色的是哪里
然后每一次就看一看在在当前的 stepSize 够不够走到那个个格,如果够,就直接跳过去,否则就算一个最后走到哪里就可以了
然后如果对于一个行,全部被染过了,那么就直接算一下最后到哪里,跳一下就可以了
然后最后如果全部格子都被染色了,就退出了
因为我们考虑到每一次他都会转向,然后走的步数多且每次不一样,所以事实上很快地图就会被填完
所以期望时间复杂度是 O(rc) 的
但是可能常数会有点大。。所以我卡了好一会的常数才过。还有要注意的是,输出最好用putchar,在我用printf的时候,本机 9 10s ,改了时候 1s 不到就跑出来了
CODE:
(因为怕写错,所以我全部没有用偏移量+for,而是选择了认真地手写了4种情况,所以代码很长。。)
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int N=2005;
int r,c,i,j;
LL n;//地图范围 出生点 走了多少步
LL A,B,C,D;//向上走了多少步 向右走了多少步 向下走了多少步 向左走了多少步
LL E[4];
LL F[4];
void prepare ()
{
//A=1+5+9+13+17+.....E[0]
//B=2+6+10+14+.....+E[1]
//C=3+7+11+15+...+E[2]
//D=4+8+12+16+....+E[3]
for (LL u=0;u<=3;u++)
{
LL x=n-u;
if (x%4==0) E[3]=x;
if (x%4==1) E[0]=x;
if (x%4==2) E[1]=x;
if (x%4==3) E[2]=x;
}
F[0]=(E[0]-1)/4+1;
F[1]=(E[1]-2)/4+1;
F[2]=(E[2]-3)/4+1;
F[3]=(E[3]-4)/4+1;
/*if (E[0]>0) A=(1+E[0])*(F[0])/2;
if (E[1]>0) B=(2+E[1])*(F[1])/2;
if (E[2]>0) C=(3+E[2])*(F[2])/2;
if (E[3]>0) D=(4+E[3])*(F[3])/2;*/
if (E[0]>0)
{
if (F[0]%2==0) A=((1+E[0])%r*((F[0]/2)%r))%r;
else A=(((1+E[0])/2)%r*(F[0]%r))%r;
}
if (E[1]>0)
{
if (F[1]%2==0) B=((2+E[1])%c*((F[1]/2)%c))%c;
else B=(((2+E[1])/2)%c*(F[1]%c))%c;
}
if (E[2]>0)
{
if (F[2]%2==0) C=((3+E[2])%r*((F[2]/2)%r))%r;
else C=(((3+E[2])/2)%r*(F[2]%r))%r;
}
if (E[3]>0)
{
if (F[3]%2==0) D=((4+E[3])%c*((F[3]/2)%c))%c;
else D=(((4+E[3])/2)%c*(F[3]%c))%c;
}
A=A-C;//向上走了多少步
B=B-D;//向右走了多少步
i=i-A;j=j+B;
if (i>r) {i%=r;if (i==0) i=r;}
else if (i<=0) i=i%r+r;
if (j>c) {j%=c;if (j==0) j=c;}
else if (j<=0) j=j%c+c;
//while (i>r) i-=r;while (i<=0) i+=r;
//while (j>c) j-=c;while (j<=0) j+=r;
}
int g[N][N];//这个点是什么状态 0:@ 其他就是字母
int f[4][N][N];//往上的并查集 往下的并查集 往左的并查集 往右的并查集 这个点下一个有用的是什么
int find01(LL op,LL x,LL y){return f[op][x][y]==x?x:f[op][x][y]=find01(op,f[op][x][y],y);}
int find23(LL op,LL x,LL y){return f[op][x][y]==y?y:f[op][x][y]=find23(op,x,f[op][x][y]);}
int xx[N],yy[N];//第i行,或者第j列删剩了多少
int tot=0;//一共删了多少个点
void Del (LL x,LL y)
{
tot++;
xx[x]++;yy[y]++;
f[0][x][y]--;if (f[0][x][y]<1) f[0][x][y]+=r;
f[1][x][y]++;if (f[1][x][y]>r) f[1][x][y]-=r;
f[2][x][y]--;if (f[2][x][y]<1) f[2][x][y]+=c;
f[3][x][y]++;if (f[3][x][y]>c) f[3][x][y]-=c;
}
LL dis1 (int x,int y)//横着x走到y的距离
{
if (x<=y) return y-x;
return y+c-x;
}
LL dis0 (int x,int y)//竖着x走到y的距离
{
if (x<=y) return y-x;
return y+r-x;
}
void solve ()
{
memset(xx,0,sizeof(xx));memset(yy,0,sizeof(yy));
int d,col;
LL now;//当前的方向是什么 1:向上走 2:向右走 3:往下走 0:向左走
//当然,方向要反过来
col=n%26;
d=n%4;
for (LL u=n;u>=1;u--)//模拟过程,那么这个点就要走这个多步
{
if (tot==r*c) break;
LL now=u;//还要走多少步
if (col==0) col=26;
if (d==-1) d=3;
if (d==0)//向右走
{
while (true)
{
if (xx[i]==c)
{
j=j+now%c;//到达这个点
j=j%c;if (j==0) j=c;
//while (j>r) j-=r;
break;
}
int jj=find23(3,i,j);//找到下一个
if (dis1(j,jj)>now)//不够走过去
{
j=j+now%c;
j=j%c;if (j==0) j=c;
//while (j>r) j-=r;
break;
}
now=now-dis1(j,jj);
j=jj;
g[i][j]=col;
Del(i,j);
}
}
if (d==1)//向下走
{
while (true)
{
if (yy[j]==r)
{
i=i+now%r;
i=i%r;if (i==0) i+=r;
//while (i>c) i-=c;
break;
}
// printf("%lld ",yy[j]);
int ii=find01(1,i,j);
// printf("new_i:%lld\n",yy[j]);
if (dis0(i,ii)>now)//不够
{
i=i+now%r;
i=i%r;if (i==0) i+=r;
//while (i>c) i-=c;
break;
}
now=now-dis0(i,ii);
i=ii;
g[i][j]=col;
Del(i,j);
// printf("%lld ",f[1][i][j]);
}
}
if (d==2)//向左走
{
while (true)
{
if (xx[i]==c)
{
j=j-now%c;//到达这个点
//while (j<=0) j+=r;
if (j<=0) j=j%c+c;
break;
}
int jj=find23(2,i,j);//找到下一个
if (dis1(jj,j)>now)//不够走过去
{
j=j-now%c;
//while (j<=0) j+=r;
if (j<=0) j=j%c+c;
break;
}
now=now-dis1(jj,j);
j=jj;
g[i][j]=col;
Del(i,j);
}
}
if (d==3)//向上走
{
while (true)
{
// printf("%d %d\n",i,j);
if (yy[j]==r)
{
i=i-now%r;
if (i<=0) i=i%r+r;
break;
}
int ii=find01(0,i,j);
if (dis0(ii,i)>now)//不够
{
i=i-now%r;
//while (i<=0) i+=c;
if (i<=0) i=i%r+r;
break;
}
now=now-dis0(ii,i);
i=ii;
g[i][j]=col;
Del(i,j);
}
}
col--;
d--;
}
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
scanf("%d%d%d%d%lld",&r,&c,&i,&j,&n);
prepare();
// printf("NO:%d %d\n",i,j);
//printf("n:%lld\n",n);
memset(g,-1,sizeof(g));
int I=i,J=j;
for (int u=1;u<=r;u++)
for (int i=1;i<=c;i++)
{
f[0][u][i]=f[1][u][i]=u;
f[2][u][i]=f[3][u][i]=i;
}
//printf("YES:%d %d\n",i,j);
solve();
g[I][J]=0;
for (int u=1;u<=r;u++)
{
for (int i=1;i<=c;i++)
{
if (g[u][i]==-1) putchar('.');
else if (g[u][i]==0) putchar('@');
else putchar(g[u][i]-1+'A');
}
putchar('\n');
}
return 0;
}