TopCoder Open 2011 Qual 3

本番は参加していないのでPractice.

Result

248.06 / 445.38 / 616.35

Easy AllButOneDivisor

問題概要

n個の整数divisorsが与えられる。
これらのうち、ちょうどn-1個の倍数となっているような整数を求めよ。
複数あるときはそのうち最小のものを、存在しない場合は-1を返せ。

方針

倍数にしない整数を一つ決めて、残りの数のLCMを取る。
更にそれが、倍数にしない数で割り切れなければそれは答えの候補。


これをn通り試して最小のものを取ればよい。

ソースコード
class AllButOneDivisor {
	public:
	int getMinimum(vector <int> divisors) 
	{
		int n=divisors.size(), ans=inf;
		rep(i,n){
			int t=1,cnt=0;
			rep(j,n)if(i!=j)t=t*divisors[j]/__gcd(t,divisors[j]);
			rep(j,n)if(t%divisors[j]==0)cnt++;
			if(cnt==n-1)ans=min(ans,t);
		}
		return ans==inf?-1:ans;
	}
};

Medium CoinMachinesGame

問題概要

いくつかのゲームがあり、それぞれプレイするのにneed[i]のお金が必要。
プレイ後にはgive[i]のお金が戻ってくる。
お金をcoinsだけもっているとき、最大で何回ゲームをプレイできるか。
同じゲームを何回プレイしてもよい。


coins≦10^9

方針

1ゲーム後に実質的に消費するのはneed[i]-give[i]枚のコイン。


ゲームi,jのどちらもプレイできるとき、
need[i]-give[i]≦need[j]-give[j]ならば、ゲームjをするかわりにゲームiをしたとしても、(残ってるお金はiをプレイした場合のほうが多いので)遊べるゲームの数は減らない。
したがってneed[i]-give[i]が最小になるiからgreedyにプレイできるだけプレイするのが最適。


coinsの枚数が多いので、そのゲームで何回遊べるかは、
coinsからneed[i]を引いてから割り算することで速く計算する。

ソースコード
class CoinMachinesGame {
	public:
	int maxGames(int coins, vector <int> need, vector <int> give) 
	{
		int n=need.size(), ans=0;
		pair<int,pi> p[100];
		rep(i,n)p[i]=mp(need[i]-give[i],mp(need[i],give[i]));
		sort(p,p+n);
		
		while(1){
			int i,t;
			for(i=0;i<n;i++)if(p[i].second.first<=coins)break;
			if(i>=n)break;
			t=(coins-p[i].second.first)/p[i].first;
			coins-=t*p[i].first; ans+=t;
			//cerr<<t<<" "<<coins<<endl;
			while(coins>=p[i].second.first)ans++, coins-=p[i].first;
		}
		return ans;
	}
};

Hard AllButOneDivisor

問題概要

各成分が0または1の行列が与えられる。
この行列について

  • i行目以上の0,1を全て入れ替える
  • i行目以下の0,1を全て入れ替える
  • j列目とそれより左の0,1を全て入れ替える
  • j列目とそれより右の0,1を全て入れ替える

操作ができるとする。


この操作を好きなだけ行った後にできる、0の長方形のうち面積が最大のものの面積を求めよ。

方針

「操作」はi列目だけの0,1を反転させる、j列目だけの0,1を反転させると読み替えてよい。


ある長方形が作れるかを考える。
長方形の一列目と二列目は、全く同じか、二列目が一列目を反転させたものでなくてはならない。
一列目と三列目、四列目……についても同じ。


全ての長方形についてこれを判定して、作れるかどうかを見てやればよい。

ソースコード
class ComplementMachine2D {
	public:
	int largestSubmatrix(vector <string> matrix) 
	{
		int h=matrix.size(), w=matrix[0].size(), ans=max(h,w);
		ll bit[50]={};
		rep(i,h)rep(j,w)if(matrix[i][j]=='1')bit[i]^=1ll<<j;
		
		rep(b,h)rep(l,w)for(int r=l+1;r<w;r++){
			ll mask=(1ll<<r-l+1)-1;
			ll ptn=bit[b]>>l&mask,ptn2;
			int t=b+1;
			for(;t<h;t++){
				ptn2=bit[t]>>l&mask;
				if(ptn!=ptn2&&ptn!=(~ptn2&mask))break;
			}
			ans=max(ans,(t-b)*(r-l+1));
		}
		return ans;
	}
};