大模拟+置换理论
就是按要求把每个操作都实现一遍,然后常规的找循环节,然后答案显然是所有循环节的最小公倍数。
感觉自己写长代码,大模拟的能力很弱,主要是因为自己找小错误能力太弱(其实啥都弱),代码一长,更多的小细节会遗漏和出错,而自己却写得很爽并且浑然不知,然后连样例都过不了,还以为是思路或者方法出了问题,反复测试都找不到问题。
解决办法:大模拟这种东西是最考验踏实程度的题目了。首先要运筹帷幄,思考一下整个程序的框架,大概需要哪些功能,要用写哪些函数,会用哪些算法,可否实现以及如何实现。在一开始编写代码的时候,就应该小心翼翼,稳稳地去实现每一个细节,反复检查,极大地降低出错的可能性。写完后如果出现了问题,根据情况认真地检查每一个功能实现的细节或者整体的框架之间的协同。
上面提到了很多次要仔细。那是因为:
随便检查十遍不如认真检查一遍。
还要提一点,那就是:
带入样例+自编数据,然后一步一步跑也是一个不错的选择,优点是偷懒+快速找到思维死角,缺点是碰运气。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
ll n;
ll vis[1100][1100];
vector<ll>op;
pll rot(pll a)
{
return make_pair(n-a.second+1,a.first);
}
pll rot_(pll a)
{
return make_pair(a.second,n-a.first+1);
}
pll sym(pll a)
{
return make_pair(a.first,n-a.second+1);
}
pll vsm(pll a)
{
return make_pair(n-a.first+n/2+1,a.second);
}
pll div(pll a)
{
if(a.first&1) return make_pair((a.first+1)/2,a.second);
else return make_pair(a.first/2+n/2,a.second);
}
pll div_(pll a)
{
if(a.first<=n/2) return make_pair(a.first*2-1,a.second);
else return make_pair(2*(a.first-n/2),a.second);
}
pll mix_(pll a)
{
if(a.first&1) return make_pair(a.first+((a.second&1)?0:1),(a.second+1)/2);
else return make_pair(a.first-((a.second&1)?1:0),n/2+(a.second+1)/2);
}
pll mix(pll a)
{
if(a.second<=n/2) return make_pair(((a.first+1)/2)*2-1,2*a.second-((a.first&1)?1:0));
else return make_pair(((a.first+1)/2)*2,2*(a.second-n/2)-((a.first&1)?1:0));
}
ll id(string s)
{
if(s=="id") return 0;
else if(s=="id-") return 0;
else if(s=="rot") return 1;
else if(s=="rot-") return 2;
else if(s=="sym") return 3;
else if(s=="sym-") return 3;
else if(s=="bhsym") return 4;
else if(s=="bhsym-") return 5;
else if(s=="bvsym") return 6;
else if(s=="bvsym-") return 7;
else if(s=="div") return 8;
else if(s=="div-") return 9;
else if(s=="mix") return 10;
else if(s=="mix-") return 11;
else return -1;
}
ll gcd(ll a,ll b)
{
return !b?a:gcd(b,a%b);
}
ll lcm(ll a,ll b)
{
return a/gcd(a,b)*b;
}
ll dfs(pll s,pll c,ll d)
{
vis[c.first][c.second]=1;
if(d!=0&&s==c) return d;
else
{
vis[c.first][c.second]=1;
for(ll i=op.size()-1;~i;i--)
{
switch (op[i])
{
case 0:break;
case 1:c=rot(c);break;
case 2:c=rot_(c);break;
case 3:c=sym(c);break;
case 4:
case 5:if(c.first>n/2)
{
c=sym(c);
}
break;
case 6:
case 7:
if(c.first>n/2)
{
c=vsm(c);
}
break;
case 8:c=div(c);break;
case 9:c=div_(c);break;
case 10:c=mix(c);break;
case 11:c=mix_(c);break;
}
}
return dfs(s,c,d+1);
}
}
ll a[25][25];
void init()
{
for(ll i=1,j=n/2,J=n/2+1;i<=n;i++)
{
a[i][j]=a[i][J]=1;
if((i&1)==0)
{
j--;
J++;
}
}
for(ll j=4;j<=17;j++)
a[14][j]=1;
}
ll NEW[25][25];
void demo()
{
for(ll i=1;i<=n;i++)
{
for(ll j=1;j<=n;j++)
{
pll temp=make_pair(i,j);
ll num=8;
while(num--)
{
temp=div(temp);
temp=rot(temp);
temp=div(temp);
temp=rot_(temp);
}
NEW[temp.first][temp.second]=a[i][j];
}
}
for(ll i=1;i<=n;i++)
{
for(ll j=1;j<=n;j++)
if(NEW[i][j]) printf("1 ");
else printf(" ");
puts("");
}
}
ll get(ll i,ll j)
{
pll s=make_pair(i,j);
pll c=s;
ll d=0;
while(d==0||s!=c)
{
vis[c.first][c.second]=1;
for(ll k=op.size()-1;k>=0;k--)
{
switch (op[k])
{
case 0:break;
case 1:c=rot(c);break;
case 2:c=rot_(c);break;
case 3:c=sym(c);break;
case 4:
case 5:if(c.first>n/2)
{
c=sym(c);
}
break;
case 6:
case 7:
if(c.first>n/2)
{
c=vsm(c);
}
break;
case 8:c=div(c);break;
case 9:c=div_(c);break;
case 10:c=mix(c);break;
case 11:c=mix_(c);break;
}
}
d++;
}
//printf("%lld\n",d);
return d;
}
int main()
{
//n=20;
//init();
//demo();
//return 0;
ll T;
scanf("%lld",&T);
while(T--)
{
memset(vis,0,sizeof(vis));
op.clear();
scanf("%lld",&n);
char str[10010];
cin.getline(str,10010);
cin.getline(str,10010);
string s=str;
stringstream ss(s);
while(ss>>s)
op.push_back(id(s));
ll ans=1;
for(ll i=1;i<=n;i++)
for(ll j=1;j<=n;j++)
if(!vis[i][j])
ans=lcm(ans,get(i,j));
printf("%lld\n",ans);
if(T) puts("");
}
return 0;
}