SRM-427 600pt: LocateTreasure

keyword

シミュレーション C++

問題概要

(0,0)の地点に北を向いた人がいる。C=1とする。その人はK(<10^9)回次の様な動きをする。

  • 向きにしたがってCだけ歩き、右を向く。
  • C = digitRoot(C*multi)とする。

最終的な座標を求める問題。

解法

状態は向きとCで考えても9*4通りしかないのでループが出てくる。その間は適当にスキップする。

感想

これで600?それはともかく、実装の遅さが本格的に痛い。

bool visited[20];
int64 py[20];
int64 px[20];
int dist[20];
int next[20];
char ans[100];

string location(int K, int multi) {
    int start=-1, cur=1, dd=0;
    int64 gx=0, gy=0;
    visited[1] = true;
    dist[1] = dd++;
    py[1] = gy;
    px[1] = gx;
    while(1){
        int tmp = cur;
        gy += cur; cur = (cur*multi+8)%9+1;
        if(!(--K)) break;
        gx += cur; cur = (cur*multi+8)%9+1;
        if(!(--K)) break;
        gy -= cur; cur = (cur*multi+8)%9+1;
        if(!(--K)) break;
        gx -= cur; cur = (cur*multi+8)%9+1;
        if(!(--K)) break;
        if(visited[cur]){
            int period = 4*(dd - dist[cur]);
            gy += (gy - py[cur])*(K/period);
            gx += (gx - px[cur])*(K/period);
            K %= period;
            if(!K) break;
        }
        else{
            visited[cur] = true;
            py[cur] = gy;
            px[cur] = gx;
            dist[cur] = dd++;
        }
    }

    sprintf(ans, "%lld %lld", gx, gy);
    return string(ans);
}