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;

}

 

你可能感兴趣的:(dijkstra)