这题思路蛮巧妙的……中午过了下午再看觉得自己能想到这方法真神奇……
题意是说,给一个R*C的方格,里面从左上到右下填满了1到R*C的数。另外给了一个(R-1)*(C-1)的操作矩阵。现在进行N次操作,每次操作中,记录当前位置的数,进行对应位置的操作,当前位置移动到右侧一格或直接换行(只在(R-1)*(C-1)的格子中运动)。问最后每个数被记录的次数。
因为N很大,暴力枚举显然不可行。但注意到,事实上每遍历一次所有格子,每个格子中的数被转移到新的格子的规律是固定的(也就是说每次操作中,(I,J)的数一定被移动到对应的(PI,PJ),与具体的次数无关)。这样,我们首先暴力求出一次遍历后对应的置换,求出所有的循环节,同时记录各个格子(不是数,因为每次遍历后格子中的数会有不同)在这一次遍历中被记录的次数。我们先求出N除以(R-1)*(C-1)的商和余数,表示遍历的次数和剩余的次数。接着遍历所有的循环节,我们可以先求出这个循环节总共被完整遍历了多少次,再加上没有完整遍历的部分即可,同时保存最后一次时各个格子里的数分别是多少。最后,再暴力算完剩余的次数即可。
说可能说不是很清楚,看程序吧……
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
typedef long long ll;
char nu[105],mo[305][305];
int n,m,res[100005],rt[100005],nl;
int a[305][305],b[305][305],bt[305][305];
int vis[100005],pn=0,nut[105],nutt[105];
vector<int> E[100005];
ll rema[90005],sh[90005];
int main()
{
int i,j,l,I=0;
while(scanf("%d %d %s",&n,&m,nu)!=EOF)
{
memset(res,0,sizeof(res));
memset(rt,0,sizeof(rt));
for(i=0;i<n-1;i++) scanf("%s",mo[i]);
for(i=0;i<n*m;i++) bt[i/m][i%m]=b[i/m][i%m]=a[i/m][i%m]=i+1;
for(i=0;i<n-1;i++)
for(j=0;j<m-1;j++)
{
rt[b[i][j]]++;
if(mo[i][j]=='L') {int te=b[i][j];b[i][j]=b[i][j+1];b[i][j+1]=b[i+1][j+1];b[i+1][j+1]=b[i+1][j];b[i+1][j]=te;}
if(mo[i][j]=='R') {int te=b[i][j];b[i][j]=b[i+1][j];b[i+1][j]=b[i+1][j+1];b[i+1][j+1]=b[i][j+1];b[i][j+1]=te;}
}
for(i=0;i<=n*m;i++) E[i].clear();memset(vis,0,sizeof(vis));pn=0;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
int te=i*m+j+1;
if(vis[te]) continue;
E[pn].push_back(te);
while(b[(te-1)/m][(te-1)%m]!=i*m+j+1)
{
te=b[(te-1)/m][(te-1)%m];
vis[te]=1;
E[pn].push_back(te);
}
++pn;
}
//for(i=0;i<pn;i++,cout<<endl) for(j=0;j<E[i].size();j++) cout<<E[i][j]<<" ";
nl=strlen(nu);
for(i=0;i<nl;i++) nut[i]=nu[nl-1-i]-'0';
ll rem=0,css=(n-1)*(m-1);
for(j=nl-1;j>=0;j--)
{
rem=rem*10+nut[j];
nut[j]=rem/css;
rem%=css;
}
while(nl>1) if(!nut[nl-1])--nl;else break;
memset(rema,-1,sizeof(rema));
for(i=0;i<pn;i++)
{
ll cs=E[i].size();
if(rema[cs]>=0) continue;
rema[cs]=0;
memset(nutt,0,sizeof(nutt));
for(j=nl-1;j>=0;j--)
{
rema[cs]=rema[cs]*10+nut[j];
nutt[j]=rema[cs]/cs;
rema[cs]%=cs;
}
sh[cs]=0;
for(j=min(4,nl-1);j>=0;j--) sh[cs]=sh[cs]*10+nutt[j];
}
for(i=0;i<pn;i++)
{
memset(nutt,0,sizeof(nutt));
ll cs=E[i].size();
ll tet=rema[cs];
ll tett=sh[cs],sut=0;
for(j=0;j<cs;j++) sut=(sut+rt[E[i][j]])%100000;
for(j=0;j<cs;j++) res[E[i][j]]=sut*tett%100000;
ll tettt=0;
for(j=0;j<tet;j++) tettt=(tettt+rt[E[i][(cs-j)%cs]])%100000;
for(l=0;l<cs;l++)
{
res[E[i][l]]=(res[E[i][l]]+tettt)%100000;
tettt=(tettt+rt[E[i][(l+1)%cs]]-rt[E[i][(l-tet+1+cs)%cs]]+100000)%100000;
}
/*
for(j=0;j<tet;j++)
{
for(l=0;l<cs;l++)
{
res[E[i][l]]=(res[E[i][l]]+rt[E[i][(l-j+cs)%cs]])%100000;
}
}
*/
for(j=0;j<cs;j++) {bt[(E[i][j]-1)/m][(E[i][j]-1)%m]=a[(E[i][(j+tet)%cs]-1)/m][(E[i][(j+tet)%cs]-1)%m];}
}
for(l=0;l<rem;l++)
{
i=l/(m-1);j=l%(m-1);
res[bt[i][j]]++;res[bt[i][j]]%=100000;
if(mo[i][j]=='L') {int te=bt[i][j];bt[i][j]=bt[i][j+1];bt[i][j+1]=bt[i+1][j+1];bt[i+1][j+1]=bt[i+1][j];bt[i+1][j]=te;}
if(mo[i][j]=='R') {int te=bt[i][j];bt[i][j]=bt[i+1][j];bt[i+1][j]=bt[i+1][j+1];bt[i+1][j+1]=bt[i][j+1];bt[i][j+1]=te;}
}
if(I++) printf("\n");
for(i=1;i<=n*m;i++) printf("%d\n",res[i]);
}
return 0;
}