BottomCoder SRM 375 div2
points | result | time |
---|---|---|
250 | AC | 5m |
500 | AC | 12m |
1000 | AC | 9.5m |
やさしめでした。
250
原料(||<=50)の容積(ml)と質量(g)が文章で与えられる。すべての原料を混ぜ合わせたときの密度(g/ml)を答えよ。
制約がやたら多い割にはやることは簡単。決まったフォーマットの文章から数字を取り出して和を求めて割れば良い。
文章の中間はいろんな形態がとれるので、ぱぱっと正規表現を使いました。
import java.util.regex.Matcher; import java.util.regex.Pattern; public class MixtureDensity { public double getDensity(String[] ingredients) { Pattern p = Pattern.compile("^([0-9]+) .* ([0-9]+) g$"); int num = 0; int den = 0; for(String s : ingredients){ Matcher m = p.matcher(s); if(m.find()){ num += Integer.parseInt(m.group(2)); den += Integer.parseInt(m.group(1)); } } return (double)num / (double)den; } }
500
n*n(<=8*8)の盤のinitPositionの位置にDukeの駒が置かれている。この駒は上下左右に1マスずつ動ける。このDukeが同じマスを通らないように動きまわる時(全てのマスを通るとかいう必要はない)、通ったパスを表す文字列のうちの辞書順最大のものを答えよ。
答えるべきパスは「(列)(行)-(列)(行)-...」といった感じ。これを最大化するときは、列を+1するほうに動かすのを優先すれば良い。同様に考えて、右上下左の優先順位でDukeを動かす。
あとは再帰で最大のパスを探索する。優先順位は枝刈りに使う。すでに最大のパスがあったとき、現在の動きからどうやっても最大に成り得ない場合ぶったぎる。
public class DukeOnChessBoard { boolean[][] visited; int n; public String dukePath(int n, String initPosition) { visited = new boolean[n][n]; this.n = n; visited[initPosition.charAt(0)-'a'][initPosition.charAt(1)-'1'] = true; String ret = initPosition + rec(initPosition.charAt(0)-'a', initPosition.charAt(1)-'1'); if(ret.length() > 40){ ret = ret.substring(0, 20) + "..." + ret.substring(ret.length() - 20); } return ret; } int[] dc = {1, 0, 0, -1}; int[] dr = {0, 1, -1, 0}; public String rec(int c, int r) { String ret = ""; for(int i = 0;i < 4;i++){ int nc = c + dc[i]; int nr = r + dr[i]; String m = "-" + (char)(nc+'a') + (char)(nr+'1'); if(nc >= 0 && nc < n && nr >= 0 && nr < n && !visited[nc][nr] && ret.compareTo(m + "~") < 0){ visited[nc][nr] = true; String v = m + rec(nc, nr); if(ret.compareTo(v) < 0){ ret = v; } visited[nc][nr] = false; } } return ret; } }
1000
n(1<=n<=10^9)が与えられる。nではじまる数で、nの0以外のどの桁の数字でも割り切れる最小の数を求めよ。
まずnの桁を列挙してlcmを計算する。これは高々lcm(2〜9)=2520. そしてnのあとに続く桁数の小さい方から、lcmで割り切れる数が[n*i,n*i+i-1]の範囲にあるかどうかチェックする。(i=1,10,100,..)
別にlcmを求めなくてもよかったりする。いろんな解法があるね。
public class DivisibleByDigits { public long getContinuation(int n) { int lcm = 1; for(int i = n;i > 0;i /= 10){ int d = i % 10; if(d > 0){ lcm = lcm * d / gcd(lcm, d); } } for(long i = 1;;i *= 10){ long inf = ((long)n*i) % lcm; System.out.println(i + " " + inf); if(inf == 0){ return (long)n*i; }else{ long il = ((long)n*i) - inf + lcm; if(il <= (long)n*i+i-1)return il; } } // return 0; } public int gcd(int a, int b) { while(b > 0){ int c = a; a = b; b = c % b; } return a; } }