2009-12-26
過去問マラソン(#3):SRM146
過去問マラソン |   |  
  
![]()
Easy(300): RectangularGrid
- Arenaの画面おかしい...と思ったら今のマシンEditorの設定が入ってないからデフォルトだ
 - 秒殺問題...と思ったけどwidth==heightの場合に除外することにテストで気づいて1分超
 - systest一発OK
 
typedef long long ll;
#define FOR(var,from,to) for(int var=(from);var<=(to);var++)
class RectangularGrid {
 public:
  long long countRectangles(int width, int height) {
    ll cnt = 0LL;
    FOR(w,1,width){
      FOR(h,1,height){
        if (w!=h) cnt += (1LL+width-w) * (1LL+height-h);
      }
    }
    return cnt;
  }
};
			CodeProcessorとかTZTesterとか入れてもう一度
typedef long long ll;
#define FOR(var,from,to) for(int var=(from);var<=(to);var++)
class RectangularGrid {
 public:
  long long countRectangles(int width, int height) {
    ll cnt;
    FOR(w,1,width) FOR(h,1,height) if(w!=h) cnt += (1LL+width-w)*(1LL+height-h);
    return cnt;
  }
};
			- 299.11点 (1'32'')...まだ速くできるだろ
 - 一見良さそうだしローカルではTest Caseも通るんだけどsystestいきなりこける。何故かというとcntを初期化してないから...orz
 - もいちどクリアして挑戦...ローカルテストなしで299.69点(0'54'')...トップの連中はこの位は当たり前?
 
Medium(600): Masterbrain
- なんか簡単じゃない?
				
- results (black/white) は14パターン (00,01,02,03,04,10,11,12,13,20,21,22,30,40)しかない
 - 秘密の数の組み合わせも1-7の4桁なので7^4=2401通りしかない
 - あるguessに対し2401パターン全部試して、可能なパターンのビットを立てておく
 - guessは最大10回。どれかが嘘なので嘘のパターンはnotして、可能なパターンの論理積(and)を各回について取ったのがそのguessから得られる可能なパターンで、それをguess回数分取って論理和(or)を取り、立ってるビットを数えたら終わり
 
 - (途中電話がかかってきたりして数分ブレイクしたが)40'41''...絶対もっともっと速く書ける。ビット列のand,or演算とかライブラリにしておくべき
 - systest一発OK
 
typedef long long ll;
#define sz(a)  int((a).size())
#define rep(var,n)  for(int var=0;var<(n);var++)
class Masterbrain {
// BEGIN CUT HERE
  string enc(int n){ // for debug
    char s[5] = { '1'+((n/343)%7), '1'+((n/49)%7), '1'+((n/7)%7), '1'+(n%7), 0 };
    return string(s);
  }
// END CUT HERE
  int n;
  int possible(int secret, string guess, int result_b, int result_w){
    int s[4] = { (secret/343)%7, (secret/49)%7, (secret/7)%7, secret%7 };
    int g[4]; rep(i,4) g[i] = guess[i]-'1';
    int b=0, w=0; 
    rep(i,4) if(g[i]==s[i]){ b++; g[i]=s[i]=-1;}
    rep(i,4) rep(j,4) {
      if (i==j || g[i]<0 || s[j]<0) continue;
      if (g[i]==s[j]){ w++; g[i]=-1; s[j]=-1; break; }
    }
    return (b==result_b && w==result_w)?1:0;
  }
  void x_not_and(vector<int>& a, vector<int>& b){ rep(i,2401) a[i] &= (1 - b[i]); }
  void x_and(vector<int>& a, vector<int>& b){ rep(i,2401) a[i] &= b[i]; }
  void x_or(vector<int>& a, vector<int>& b){ rep(i,2401) a[i] |= b[i]; }
  
 public:
  int possibleSecrets(vector <string> guesses, vector <string> results) {
    // secret: 7^4 = 2401 patterns
    n = sz(guesses); // 1..10
    vector<vector<int> > bits(n);
    rep(i,n){
      const char *s = results[i].c_str();
      int b = s[0]-'0', w = s[3]-'0';
      vector<int> bit(2401,0);
      rep(n,2401){
        bit[n] = possible(n,guesses[i],b,w);
      }
      bits[i] = bit;
    }
    vector<int> possibles(2401,0);
    rep(u,n){ // どれを嘘と仮定するか
      vector<int> a(2401,1);
      rep(i,n){
        if(i==u){
          x_not_and(a,bits[i]);
        } else {
          x_and(a,bits[i]);
        }
      }
      
      x_or(possibles,a);
    }
    int bitcnt=0;
    rep(i,2401) bitcnt+=possibles[i];
    return bitcnt;
  }
};
			勉強がてらビット列を表現するクラスを作ってみて今では
typedef long long ll;
#define sz(a)  int((a).size())
#define rep(var,n)  for(int var=0;var<(n);var++)
#include "Bits.h"
string enc(int n){ // n:0..2400 => "1234"
  char s[5] = { '1'+((n/343)%7), '1'+((n/49)%7), '1'+((n/7)%7), '1'+(n%7), 0 };
  return string(s);
}
int dec(string s){ // s:"1234" => (0..2400)
  int res = 0;
  rep(i,4) res = res*7 + (s[i] - '1');
  return res;
}
class Masterbrain {
  int n;
  int possible(int secret_n, string guess, int result_b, int result_w){
    string s = enc(secret_n), g = guess;
    int b=0, w=0; 
    rep(i,4) if(g[i]==s[i]){ b++; g[i]=s[i]=-1;}
    rep(i,4) rep(j,4) {
      if (i==j || g[i]<0 || s[j]<0) continue;
      if (g[i]==s[j]){ w++; g[i]=-1; s[j]=-1; break; }
    }
    return (b==result_b && w==result_w)?1:0;
  }
 public:
  int possibleSecrets(vector <string> guesses, vector <string> results) {
    // secret: 7^4 = 2401 patterns
    n = sz(guesses); // 1..10
    vector<Bits> bits(n, Bits(2401,0));
    rep(i,n){
      int b = results[i][0]-'0', w = results[i][3]-'0';
      rep(j,2401) bits[i].set(j, possible(j,guesses[i],b,w));
    }
    Bits possibles(2401,0);
    rep(u,n){
      Bits a(2401,1);
      rep(i,n){
        if (i==u) a &= ~bits[i];
        else      a &=  bits[i];
      }
      possibles |= a;
    }
    return possibles.popcount();
  }
};
			- Bitsクラス(現時点で200行強)は別エントリ立てる
 
Hard(800): Roundabout
// later
コメント
	トラックバック - https://topcoder-g-hatena-ne-jp.jag-icpc.org/n4_t/20091226