topcoder srm 450 div1

problem1 link

用$f[i][0],f[i][1]$表示从$i$位置开始Alice是先手是否可以胜利,是后手是否可以胜利。

problem2 link

每次钱数够$price$时可以选择使得$n$或者$k$中较小的一个增加1。最多也就增加$2*10^{6}$次。钱数不够$price$时可以直接算出还要多少次可以够$price$。每一次也可以直接计算出不再变化$n,k$而直接挣够$target$时的次数。

problem3 link

如果$k$足够大,最后一定是在某一个区间$[L,R]$循环。当从左到右到达$R$之后,其要选择的循环的$L$一定是满足使得$sum(i,R)$最大的$i$。

那么现在就是应该尽快第一次到达$R$。

设$minTime[i],maxScore[i]$表示从0到达$i$并且下一次应该朝左时最小次数,以及在次数最小情况下最大的分数。

那么每次到达$i$时,一定是在$i$进行了若干次循环$[x,i]$后,从$i$到达了后面的某个$j$。在$i$循环的次数就是满足到达$j$不为负值的最小值。

code for problem1

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class OrderedNim {
	
	public String winner(int[] layout) {
		final int n = layout.length;
		boolean s0 = true;
		boolean s1 = false;
		for (int i = n - 2; i >= 0; --i) {
			boolean t0, t1;
			if (layout[i] == 1) {
				t0 = s1;
				t1 = s0;
			}
			else {
				if (s0 || s1) {
					t0 = true;
					t1 = false;
				}
				else {
					t0 = false;
					t1 = true;
				}
			}
			s0 = t0;
			s1 = t1;
		}
		if (s0) {
			return "Alice";
		}
		return "Bob";
	}
}

  

code for problem2

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class StrongEconomy {
	
	public long earn(long n, long k, long price, long target) {
		if (n >= (target + k - 1) / k) {
			return 1;
		}
		long result = Long.MAX_VALUE;
		long usedDays = 0;
		long sum = 0;
		while (n * k < target) {
			long speed = n * k;
			result = Math.min(result, usedDays + (target - sum + speed - 1) / speed);
			if (sum < price) {
				long d = (price - sum + speed - 1) / speed;
				sum += speed * d;
				usedDays += d;
			}
			sum -= price;
			if (n < k) {
				++n;
			}
			else {
				++k;
			}
		}
		result = Math.min(result, usedDays + 1);
		return result;
	}
}

  

code for problem3

import sun.rmi.runtime.Log;

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class RowGame {
	
	public long score(int[] board, int k) {
		final int n = board.length;

		long[] lmax = new long[n];
		for (int i = 0; i < n; ++ i) {
			lmax[i] = Long.MIN_VALUE;
			long s = 0;
			for (int j = i; j >= 0; --j) {
				s += board[j];
				lmax[i] = Math.max(lmax[i], s);
			}
		}

		long[] minTimes = new long[n];
		long[] maxScore = new long[n];
		long tmp = 0;
		for (int i = 0; i < n; ++i) {
			minTimes[i] = Long.MAX_VALUE;
			tmp += board[i];
			if (tmp >= 0) {
				minTimes[i] = 1;
				maxScore[i] = tmp;
			}
		}

		long result = 0;
		for (int i = 0; i < n; ++i) {
			if (minTimes[i] > k) {
				continue;
			}
			result = Math.max(result, maxScore[i] + lmax[i] * (k - minTimes[i]));
			if (lmax[i] <= 0) {
				continue;
			}
			tmp = maxScore[i];
			for (int j = i + 1; j < n; ++j) {
				tmp += board[j];
				long t = (- tmp + 2 * lmax[i] - 1)/(2 * lmax[i]);
				if ( t <= 0) {
					t = 1;
				}
				long newTimes = minTimes[i] + t * 2;
				long newScore = tmp + lmax[i] * t * 2;
				if (minTimes[j] > newTimes || minTimes[j] == newTimes && maxScore[j] < newScore) {
					minTimes[j] = newTimes;
					maxScore[j] = newScore;
				}
			}
		}
		return result;
	}
}

  

posted @ 2017-10-28 16:53  朝拜明天19891101  阅读(289)  评论(0编辑  收藏  举报