Hatena::Grouptopcoder

kojingharangの日記 RSSフィード

 | 

2013-11-02

SRM 593 Div1 250 IncrementAndDoubling

09:50 |  SRM 593 Div1 250 IncrementAndDoubling - kojingharangの日記 を含むブックマーク はてなブックマーク -  SRM 593 Div1 250 IncrementAndDoubling - kojingharangの日記  SRM 593 Div1 250 IncrementAndDoubling - kojingharangの日記 のブックマークコメント

  • 長さNで全部0の配列に対して(1)どれかに1を足す,(2)全部を2倍する, を繰り返して別途与えられる長さNの配列Dと等しくしたい。最小手数を求める。
  • 1≦N≦50, 0≦D[i]≦1000
  • できるかぎり2倍は使った方が良いだろう(証明なし)
  • ビット表現で1になってるとこは必ず1を足す操作で作られるはず。タイミングは2倍2倍に増えてく途中でここぞというときにやればいい
  • なので一番大きな数に対して2倍を適用する回数 + 全ての数のbit countが答え
  • accepted

class IncrementAndDoubling {
	public:
	int getMin(vector <int> D) {
		int ans = 0;
		REP(i, D.size()) ans += POPCOUNT(D[i]);
		int mx = 0;
		REP(i, D.size()) mx=max(mx, D[i]);
		while(mx>1) { ans++;mx>>=1;}
		return ans;
	}
};



SRM 593 Div1 500 BitwiseAnd

09:50 |  SRM 593 Div1 500 BitwiseAnd - kojingharangの日記 を含むブックマーク はてなブックマーク -  SRM 593 Div1 500 BitwiseAnd - kojingharangの日記  SRM 593 Div1 500 BitwiseAnd - kojingharangの日記 のブックマークコメント

  • Nと、N以下の要素を持つlong long配列Sが与えられる。
  • S に必要ならいくつか要素を追加して、(1)任意の2組のAND>0, (2)任意の3組のAND==0, (3)数値は1以上2^60-1以内, になるような辞書順最小の配列を求めよ。
  • 3≦N≦50, 1≦S[i]≦2^60-1
  • ビット表現にして配列を各行に書いてくと...
  • 各列に1がちょうど2個あって、任意のi, jにたいして行iと行jが連結(どちらも1の列がある)してればOK
  • 連結状態を行列で管理してみる
  • すでに3つ以上あるときはだめ
  • 追加する数字に関しては、
  • すべての列に対して、縦に見て1の数を数えて、1個なら連結じゃないので連結できそうな行を見つけて1を書いていく
  • 連結じゃないときは全ての列が0であるとこを探して無理やり1を2つ書いて連結にする
  • でいいと思われる
001100011  //99
010011101  //157
?????????
?????????

001100011  //99
010011101  //157
100000110  //262
100101000  //296

Returns: {99, 157, 262, 296 }
  • バグりまくる
  • 終了
  • 書いた
  • サンプルの{}, 5が合わない
  • 紙に書いて分析。辞書順最小になってない。
  • 連結じゃないときに無理やり追加するのは毎回じゃなくて最後に1回だけにしないと辞書順最小にならないようだ
  • いろいろ証明できてなくてもやもやしてるけどpracticeで通った
  • ↓あとで(accepted in practice room)
class BitwiseAnd {
	public:
	ll add;
	VVI w;
	int N, M;
	VI S;
	bool check(bool init) {
		REP(bit, 60) {
			VI one;
			REP(i, S.size()) {
				if((S[i]>>bit)&1) one.PB(i);
			}
			if(one.size()>2) return false;
			if(one.size()==2) w[one[1]][one[0]] = w[one[0]][one[1]] = 1;
			if(!init && one.size()==1 && w[one[0]][S.size()]==0) {
				add |= 1LL<<bit;
				w[one[0]][S.size()] = w[S.size()][one[0]] = 1;
			}
		}
		if(!init) {
			S.PB(add);
		}
		REP(i, S.size()) REP(j, S.size()) {
			if(i!=j && w[i][j]==0) {
				if(init) {
					return false;
				}
			}
		}
		return true;
	}
	vector<long long> lexSmallest(vector<long long> _S, int N) {
		S=_S;
		M=S.size();
		w = VVI(N, VI(N));
		if(!check(true)) return vector<ll>();
		while(S.size()<N) {
			add=0;
			if(!check(false)) return vector<ll>();
		}
		REP(i, S.size()) REP(j, S.size()) {
			if(i!=j && w[i][j]==0) {
				if(i<M || j<M) continue;
				bool ok=false;
				REP(bit, 60) {
					bool lok=true;
					REP(k, S.size()) if((S[k]>>bit)&1) lok=false;
					if(lok) {
						ll a = 1LL<<bit;
						S[i] |= a;
						S[j] |= a;
						w[i][j]=w[j][i]=1;
						ok=true;
					}
					if(ok) break;
				}
			}
		}
		if(!check(true)) return vector<ll>();
		sort(ALL(S));
		return S;
	}
};
 |