GCJ 2015-Qualification-C Dijkstra 特殊注意,展开 难度:2
https://code.google.com/codejam/contest/6224486/dashboard#s=p2
题目中的新运算满足传递性不满足自反性,满足传递性则可以先计算后面的部分再计算前面的,明显设每节的计算结果为val,则要成功必然需要val*val^(x-1)(也就是x个val相乘)恰为-1(i*j*k==-1),因为满足传递性,所以在此条件下,只需要取前面的一部分等于i,后面一部分等于k,中间一部分就会等于j了.
注意到无论每节的结果是什么,每四节的结果一定是1,所以左边的最小长度不会大于四节(否则会多一个1出来,没有用),同样,右边也不会大于四节,所以最小长度不会大于8节,直接把字符串缩小到8节以内展开即可也就是x%8
但是需要特殊注意的是,有两种情况
1. 原本大于8,x%8之后反而不满足题意了,这需要改成x%4+4
2. 在1的基础上,原本小于4,结果给改成大于4了,所以需要特判一下只有x>8的时候x=x%4+4
接下来直接展开计算即可
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> using namespace std; typedef long long ll; const int maxl=2.5e5+10; int l; ll x; char str[maxl]; int val[maxl],rv[maxl]; int subcalc[255][255]; void initcalc(){ subcalc[1][1]=1; subcalc[1][(int)'i']=(int)'i'; subcalc[1][(int)'j']=(int)'j'; subcalc[1][(int)'k']=(int)'k'; subcalc[(int)'i'][1]=(int)'i'; subcalc[(int)'j'][1]=(int)'j'; subcalc[(int)'k'][1]=(int)'k'; subcalc[(int)'i'][(int)'j']=(int)'k'; subcalc[(int)'j'][(int)'i']=-(int)'k'; subcalc[(int)'i'][(int)'k']=-(int)'j'; subcalc[(int)'k'][(int)'i']=(int)'j'; subcalc[(int)'j'][(int)'k']=(int)'i'; subcalc[(int)'k'][(int)'j']=-(int)'i'; subcalc[(int)'i'][(int)'i']=-1; subcalc[(int)'j'][(int)'j']=-1; subcalc[(int)'k'][(int)'k']=-1; } int calc(int a,int b){ int sign=a*b/abs(a)/abs(b); a=abs(a); b=abs(b); return sign*(subcalc[a][b]); } int indi,indk; void calvalue(){ val[0]=(int)str[0]; if(val[0]==(int)'i')indi=0; else indi=0x7ffffff; indk=-1; for(int i=1;i<l;i++){ val[i]=calc(val[i-1],(int)str[i]); if(val[i]==(int)'i'){ indi=min(indi,i); } } rv[l]=1; for(int i=l-1;i>=0;i--){ rv[i]=calc((int)str[i],rv[i+1]); if(rv[i]==(int)'k'){ indk=max(indk,i); } } } int main(){ freopen("data.in","r",stdin); freopen("data.out","w",stdout); initcalc(); int T; cin>>T; for(int ti=1;ti<=T;ti++){ cin>>l>>x>>str; //printf("%d %I64d %s\n",l,x,str); if(x>8){ x=x%4+4; } for(int i=1;i<x;i++){ for(int j=i*l;j<i*l+l;j++){ str[j]=str[j-i*l]; } } l*=x; str[l]=0; calvalue(); int fl=val[l-1]; if(fl!=-1||indi>=indk){ cout<<"Case #"<<ti<<": NO"<<endl; } else { cout<<"Case #"<<ti<<": YES"<<endl; } } return 0; }