Hatena::Grouptopcoder

cafelier@SRM

cafelier のSRM参加記録です。コンテスト中に考えてたことを執拗に全部書き残すとどうなるだろうかという試み本番中にこういうコードが書きたかったなあ、という後で書いた反省コードを書き残す試み

スパムが来たのでしばらくコメント欄をはてなユーザ限定にしています、すみません、

 | 

2009-03-08

TCO Round1 1000

| 11:49 | はてなブックマーク - TCO Round1 1000 - cafelier@SRM

普段mod演算は念のためlong longでやってるのだけど、それだとTLEした。intに変えて通しました。これは本番でいくら時間があっても気づけなかった予感。

static const int MODVAL = 1000000007;
int ADD(int x, int y) { return (x+y)%MODVAL; }
int SUB(int x, int y) { return (x-y+MODVAL)%MODVAL; }

class Unicorn {
public:
  int countWays(int R, int C, int L, int seed, string word) 
  {
    // input...
    char B[300][300];
    {
      int x = seed;
      int d = (65535 / L)+1;
      for (int r=0; r<R; r++)
        for (int c=0; c<C; c++) {
          x = (x * 25173 + 13849) % 65536;
          B[r][c] = (65+(x / d));
        }
    }

    // solve
    vector<int> cnt(C*R);
    for(int r=0; r<R; ++r)
    for(int c=0; c<C; ++c)
      if( B[r][c] == word[0] )
        cnt[r*C+c] = 1;

    for(int i=1; i<word.size(); ++i)
    {
      int total_cnt = 0;
      vector<int> c_cnt(C);
      vector<int> r_cnt(R);
      for(int r=0; r<R; ++r)
      for(int c=0; c<C; ++c)
        r_cnt[r]  = ADD( r_cnt[r], cnt[r*C+c]),
        c_cnt[c]  = ADD( c_cnt[c], cnt[r*C+c]),
        total_cnt = ADD(total_cnt, cnt[r*C+c]);

      vector<int> cnt2(C*R);
      for(int r=0; r<R; ++r)
      for(int c=0; c<C; ++c)
        if( B[r][c] == word[i] )
        {
          int x = total_cnt;

          for(int rr=r-1; rr<=r+1; ++rr) if(0<=rr && rr<R)
            x = SUB(x, r_cnt[rr]);
          for(int cc=c-1; cc<=c+1; ++cc) if(0<=cc && cc<C)
            x = SUB(x, c_cnt[cc]);

          for(int rr=r-1; rr<=r+1; ++rr) if(0<=rr && rr<R)
          for(int cc=c-1; cc<=c+1; ++cc) if(0<=cc && cc<C)
            x = ADD(x, cnt[rr*C+cc]);

          for(int rr=r-2; rr<=r+2; rr+=4) if(0<=rr && rr<R)
          for(int cc=c-2; cc<=c+2; cc+=4) if(0<=cc && cc<C)
            x = SUB(x, cnt[rr*C+cc]);

          cnt2[r*C+c] = x;
        }
      cnt.swap(cnt2);
    }

    int live = 0;
    for(int r=0; r<R; ++r)
    for(int c=0; c<C; ++c)
      live = ADD(live, cnt[r*C+c]);
    return live;
  }
};

ユニコーンのいけないところを列単位行単位でまとめておいて数えるとO(1)でひとつの遷移を計算できる

トラックバック - https://topcoder-g-hatena-ne-jp.jag-icpc.org/cafelier/20090308
 | 

presented by cafelier/k.inaba under CC0