BottomCoder SRM 399 div2
http://www.topcoder.com/stat?c=round_overview&rd=12171
point | result | time |
---|---|---|
250 | AC | 4m |
500 | AC | 3.5m |
1000 | WA1 | 17m |
1000解いて余裕かましてたら凡ミスに気づいて直してたら終了した('A`)
250
駅(||<=50)とそれら全てをつなぐ環状線がある。隣り合う駅間の線路長t[]が与えられたとき、異なる2つの駅間の最短経路長の最大値を求めよ。
駅A,Bについて、Aのインデックス
public class CircularLine { public int longestTravel(int[] t) { int n = t.length; int max = 0; for(int i = 0;i < n;i++){ for(int j = i;j < n;j++){ max = Math.max(max, Math.min(dur(t, i, j), dur(t, j, i))); } } return max; } int dur(int[] t, int a, int b) { int sum = 0; if(a <= b){ for(int i = a;i <= b - 1;i++){ sum += t[i]; } }else{ for(int i = a;i < t.length;i++){ sum += t[i]; } for(int i = 0;i <= b - 1;i++){ sum += t[i]; } } return sum; } }
500
k(<=20)個の整数a_i(i=1,...,k)を考える。これらの合計がS(<=1000)のとき、これらすべての積の最大値を求めよ。
えっこれ平均まわりだろ?と直後に思ってさくさくかいた。反例が思いつかなかったのでsubmit.
整数計画だと思う。a_iが実数だと、a_i=S/kが最適になるので、S%k個を[S/k]+1, k-(S%k)個を[S/k]として積を求めれば良い。
証明は・・一方が[S/k],[S/k]+1でないペアと、どちらも[S/k],[S/k]+1でできたペアをつくって、和が等しいときに積がどうなるかを調べると・・あとは帰納でいけるのかな。
public class MaximalProduct { public long maximalProduct(int s, int k) { int av = s / k; long ret = 1; for(int i = 0;i < s%k;i++)ret *= av+1; for(int i = 0;i < k-s%k;i++)ret *= av; return ret; } }
1000
n-xyz | を最小化する整数の3つ組(x,y,z)(x<=y<=z)を求めよ。n<=1000. ただし、集合a( | <=50)にある整数(<=1000)はx,y,zに使ってはいけない。 |
xyz<=Mのとき、x,y,zのいずれかが必ず集合aにはいってしまうようなMの最大値を考える。aに含まれない最小の値をQとすると、x=y=z=Qのときはその制約を満たさないため、M
import java.util.BitSet; public class AvoidingProduct { public int[] getTriple(int[] a, int n) { int N = 51*51*51; int min = N+1; int ox, oy, oz; ox = oy = oz = -1; BitSet mask = new BitSet(); for(int q : a){ mask.set(q); } for(int x = 1;x*x*x <= N;x++){ if(mask.get(x))continue; for(int y = x;x*y*y <= N;y++){ if(mask.get(y))continue; for(int z = y;x*y*z <= N;z++){ if(mask.get(z))continue; int d = Math.abs(n - x*y*z); if(d < min){ min = d; ox = x; oy = y; oz = z; } } } } return new int[]{ox, oy, oz}; } }