zoukankan      html  css  js  c++  java
  • topcoder srm 490 div1

    problem1 link

    首先每$n*m$一定是一个循环,所以只需要考虑时间$[0,n*m-1]$即可。这个期间一共出现了$n$个,第i个的出现时间为$m*i$,离开的时间为$left lceil frac{mi}{n} ight ceil*n$,所有答案为:

    ans=$frac{sum_{i=0}^{n-1}(left lceil frac{mi}{n} ight ceil*n-mi)}{n}$

    =$frac{nsum_{i=0}^{n-1}left lceil frac{mi}{n} ight ceil-sum_{i=0}^{n-1}mi}{n}$

    =$sum_{i=0}^{n-1}left lceil frac{mi}{n} ight ceil-frac{(n-1)m}{2}$

    设$A=sum_{i=0}^{n-1}left lceil frac{mi}{n} ight ceil=sum_{i=0}^{n-1}left lfloor frac{mi}{n} ight floor+n-X$ 

    其中$X$是那些$mi$正好是$n$的倍数因此不需要加1的个数。

    现在的问题是计算$B=sum_{i=0}^{n-1}left lfloor frac{mi}{n} ight floor$

    它等于$sum_{i=0}^{n-1}left lfloor frac{mi}{n} ight floor=frac{(n-1)(m-1)}{2}-frac{gcd(n,m)-1}{2}$

    这个的证明在具体数学中文版第二版第77页到第78页。

    problem2 link

    首先将所有的前缀编号,预处理转换表$T[id][k]$表示前缀id在输入$k$时转换到的状态,其中$k$表示数字以及星号。

    然后设$f[i][id]$表示当前“fix”部分为$word$的前$i$个,且"unfix"部分的标号为id的最小操作次数。然后进行dp即可。

    problem3 link

    首先,在$n*m$个一个pattern中(n为高度,m为宽度),位置$(x_{1},y_{1})$到位置$(x_{2},y_{2})$的最短路径可能会经过其他重复的pattern。可以证明,如果经过该patern上面的pattern,最多只需要考虑$left lceil frac{m}{2} ight ceil^{2}$个

    假设每次进入上面一个pattern是进入是第$i$列,出来时是第$j$列,$i e j$。那么不会出现两个pattern进入出来时的$i,j$一模一样,否则可以省略中间的一些pattern。这样考虑的话不同的$i,j$对有$frac{m(m-1)}{2}$个,所以至多向上考虑这么多即可。

    进一步考虑。将pattern的最后一行按照连续的空列分成若干组,那么很明显最多有$left lceil frac{m}{2} ight ceil$组(每隔一个空列有一个障碍格子)。跟上面同样的考虑方法,进入的组和出来的组不会有两个pattern是完全一样的,否则可以省略(因为一个组是联通的)。所以向上最多需要考虑$left lceil frac{m}{2} ight ceil^{2}$个pattern即可。

    这样就可以处理出一个$m*m$的矩阵$A[i][j]$,表示从pattern的第一行的第 $i$ 列格子到达下一个pattern的第一行的第$j$列格子的最短路径。

    这样的话,对于那么$r_{1},r_{2}$中间有很多pattern的情况,可以进行类似矩阵幂的优化。

    code for problem1

    import java.util.*;
    import java.math.*;
    import static java.lang.Math.*;
    
    public class Starport {
    
    	public double getExpectedTime(int N, int M) {
    		long t = (long)(N - 1) * M;
    		long r = upper(N, M) - t / 2;
    		if (t % 2 == 0) {
    			return r;
    		}
    		return r - 0.5;
    	}
    
    	long upper(long n, long d) {
    		if (n == 1) {
    			return 0;
    		}
    		long nn = n / gcd(n, d);
    		long p = (n - 1) / nn + 1;
    		return lower(n, d) + n - p;
    	}
    
    	long gcd(long x, long y) {
    		if (y == 0) {
    			return x;
    		}
    		return gcd(y, x % y);
    	}
    
    	long lower(long n, long m) {
    		return ((n - 1) * (m - 1) + gcd(n, m) - 1) / 2;
    	}
    
    }
    

      

    code for problem2

    import java.util.*;
    import java.math.*;
    import static java.lang.Math.*;
    
    public class QuickT9 {
    
    	static int[] D = new int[]{3, 3, 3, 3, 3, 4, 3, 4};
    
    	int prefixIndex = 0;
    	Map<String, Integer> map = new HashMap<>();    //串对应编号
    	Map<Integer, String> mapRev = new HashMap<>(); //编号对应串
    	Map<String, List<String>> mapForNext = new HashMap<>();  //数字串对应的串
    	Map<String, String> mapToDigit = new HashMap<>();        //串对应的数字串
    	List<String> allWords = new ArrayList<>();
    
    	String word;
    
    	int[][] g = null;
    	int[][] f = null;
    
    	public int minimumPressings(String[] t9, String word) {
    		init(t9);
    		this.word = word;
    		final int n = word.length();
    		f = new int[n + 1][prefixIndex];
    		for (int i = 0; i <= n; ++ i) {
    			Arrays.fill(f[i], -1);
    		}
    		f[0][0] = 0;
    		for (int i = 0; i < n; ++ i) {
    			bfs(i);
    		}
    		return f[n][0];
    	}
    
    	Queue<Integer> queue = new LinkedList<>();
    	boolean[] inq = null;
    
    	void bfs(int len) {
    		if (inq == null) {
    			inq = new boolean[prefixIndex + 1];
    		}
    
    		if (f[len][0] != -1) {
    			queue.offer(0);
    		}
    		while (!queue.isEmpty()) {
    			int st = queue.poll();
    			inq[st] = false;
    			for (int i = 0; i < 11; ++ i) {
    				if (i < 9) {
    					int nxt = g[st][i];
    					int c = f[len][st] + 1;
    					if (f[len][nxt] == -1 || f[len][nxt] > c) {
    						f[len][nxt] = c;
    						if (!inq[nxt]) {
    							queue.offer(nxt);
    							inq[nxt] = true;
    						}
    					}
    				}
    				else {
    					int[] result = check(st, len, i == 10);
    					int t = result[0];
    					int c = result[1];
    					if (t > 0) {
    						if (f[len + t][0] == -1 || f[len + t][0] > f[len][st] + 1 + c) {
    							f[len + t][0] = f[len][st] + 1 + c;
    						}
    					}
    				}
    			}
    		}
    	}
    
    	void init(String[] all) {
    		for (int i = 0; i < all.length; ++ i) {
    			String[] t= all[i].split("\W+");
    			for (String p : t) {
    				String x = p.trim();
    				if (x.length() > 0) {
    					allWords.add(x);
    				}
    			}
    		}
    		addPrefix("", "");
    		for (int i = 0; i < allWords.size(); ++ i) {
    			String originStr = "";
    			String digitStr = "";
    			String s = allWords.get(i);
    			for (int j = 0; j < s.length(); ++ j) {
    				digitStr += getDigit(s.charAt(j));
    				originStr += s.charAt(j);
    				addPrefix(originStr, digitStr);
    			}
    		}
    
    		for (String s: mapForNext.keySet()) {
    			Collections.sort(mapForNext.get(s));
    		}
    		g = new int[prefixIndex][9];
    		for (int i = 0; i < prefixIndex; ++ i) {
    			for (int j = 0; j < 9; ++ j) {
    				if (j == 0) {
    					g[i][j] = getNext(i);
    				}
    				else {
    					g[i][j] = getAddDigit(i, j + 1);
    				}
    
    			}
    		}
    	}
    
    	int[] check(int id, int preIndex, boolean isStar) {
    		if (id == 0) {
    			return new int[]{0,0};
    		}
    		String s = mapRev.get(id);
    		String sub = word.substring(preIndex);
    		if (isStar) {
    			s = s.substring(0, s.length() - 1);
    		}
    		int comPre = 0;
    		for (int i = 0; i < sub.length() && i < s.length(); ++ i) {
    			if (sub.charAt(i) == s.charAt(i)) {
    				++comPre;
    			}
    			else {
    				break;
    			}
    		}
    		return new int[]{comPre, s.length() - comPre};
    	}
    
    
    	int getNext(int id) {
    		if (id == 0) {
    			return 0;
    		}
    		String s = mapRev.get(id);
    		String digitStr = mapToDigit.get(s);
    		List<String> list = mapForNext.get(digitStr);
    		int index = list.indexOf(s);
    		String nextOriginStr = list.get((index + 1) % list.size());
    		return map.get(nextOriginStr);
    	}
    	int getAddDigit(int id, int d) {
    		String s = mapRev.get(id);
    		String digitStr0 = mapToDigit.get(s);
    		String digitStr1 = digitStr0 + (char)('0' + d);
    		if (!mapForNext.containsKey(digitStr1)) {
    			return id;
    		}
    		List<String> list = mapForNext.get(digitStr1);
    		return map.get(list.get(0));
    	}
    
    	void addPrefix(String originStr, String digitStr) {
    		if (!map.containsKey(originStr)) {
    			map.put(originStr, prefixIndex);
    			mapRev.put(prefixIndex, originStr);
    			++ prefixIndex;
    		}
    		if (!mapForNext.containsKey(digitStr)) {
    			mapForNext.put(digitStr, new ArrayList<>());
    		}
    		if (!mapForNext.get(digitStr).contains(originStr)) {
    			mapForNext.get(digitStr).add(originStr);
    		}
    		mapToDigit.put(originStr, digitStr);
    	}
    
    	static char getDigit(char c) {
    		int t = c - 'a' + 1;
    		for (int i = 0; i < D.length; ++ i) {
    			if (t > D[i]) {
    				t -= D[i];
    			}
    			else {
    				return (char)('2' + i);
    			}
    		}
    		return 0;
    	}
    }
    

      

    code for problem3

    import java.util.*;
    
    
    public class InfiniteLab {
    
    	final static int[] dx = {0, 0, 1, -1};
    	final static int[] dy = {1, -1, 0, 0};
    	final static int MAX_EXTENDED = 100;
    
    	int n, m;
    	String[] map;
    	int[][] T;
    	int[][][][] d;
    
    	public long getDistance(String[] map, long r1, int c1, long r2, int c2) {
    		if (r1 > r2) {
    			return getDistance(map, r2, c2, r1, c1);
    		}
    		if (r1 < 0 || r1 >= map.length) {
    			long det = r2 - r1;
    			long b = (Math.abs(r1) / map.length + 1) * map.length;
    			r1 = (r1 + b) % map.length;
    			return getDistance(map, r1, c1 , r1 + det, c2);
    		}
    
    		this.map = map;
    		n = map.length;
    		m = map[0].length();
    		T = new int[n][2];
    		for (int i = 0; i < n; ++ i) {
    			T[i][0] = T[i][1] = -1;
    			for (int j = 0; j < m; ++ j) {
    				if (map[i].charAt(j) == 'T') {
    					if (T[i][0] == -1) {
    						T[i][0] = j;
    					}
    					else {
    						T[i][1] = j;
    					}
    				}
    			}
    		}
    		d = new int[m][n][m][n + 1];
    		cal();
    
    		if (r2 <= n) {
    			int t = d[c1][(int)r1][c2][(int)r2];
    			if (t == Integer.MAX_VALUE) {
    				t = -1;
    			}
    			return t;
    		}
    		long[][] a = new long[m][m];
    		long[][] b = new long[m][m];
    		for (int i = 0; i < m; ++ i) {
    			for (int j = 0; j < m; ++ j) {
    				a[i][j] = -1;
    				if (d[i][0][j][n] != Integer.MAX_VALUE) {
    					a[i][j] = d[i][0][j][n];
    				}
    				if (i == j) {
    					b[i][j] = 0;
    				}
    				else {
    					b[i][j] = -1;
    				}
    			}
    		}
    		long p = r2 / n - r1 / n - 1;
    		while (p > 0) {
    			if ((p & 1) == 1) {
    				b = multipy(b, a);
    			}
    			a = multipy(a, a);
    			p >>= 1;
    		}
    		long result = -1;
    		for (int i = 0; i < m; ++ i) {
    			for (int j = 0; j < m; ++ j) {
    				if (d[c1][(int)r1][i][n] != Integer.MAX_VALUE
    						&& b[i][j] != -1
    						&& d[j][0][c2][(int)(r2 % n)] != Integer.MAX_VALUE) {
    					long w = d[c1][(int)r1][i][n] + b[i][j] + d[j][0][c2][(int)(r2 % n)];
    					if (result == -1 || result > w) {
    						result = w;
    					}
    				}
    			}
    		}
    		return result;
    	}
    
    	long[][] multipy(long[][] A, long[][] B) {
    		long[][] result = new long[m][m];
    		for (int i = 0; i < m; ++ i) {
    			for (int j = 0; j < m; ++ j) {
    				result[i][j] = -1;
    				for (int k = 0; k < m; ++ k) {
    					if (A[i][k] != -1 && B[k][j] != -1) {
    						long t = A[i][k] + B[k][j];
    						if (result[i][j] == -1 || result[i][j] > t) {
    							result[i][j] = t;
    						}
    					}
    				}
    			}
    		}
    		return result;
    	}
    
    	int trans(int x, int y) {
    		x %= n;
    		if (map[x].charAt(y) == 'T') {
    			return T[x][0] + T[x][1] - y;
    		}
    		return -1;
    	}
    	boolean empty(int x, int y) {
    		return map[x % n].charAt(y) != '#';
    	}
    	void cal() {
    		final int N = (2 * MAX_EXTENDED + 1) * n;
    		int[][] f = new int[N][m];
    		Queue<Integer> queue = new LinkedList<>();
    		for (int sx = 0; sx < n; ++ sx) {
    			for (int sy = 0; sy < m ; ++ sy) {
    				final int startX =sx + MAX_EXTENDED * n;
    				final int startY = sy;
    				while (!queue.isEmpty()) {
    					queue.poll();
    				}
    				for (int i = 0; i < N; ++ i) {
    					Arrays.fill(f[i], Integer.MAX_VALUE);
    				}
    				f[startX][startY] = 0;
    				queue.offer(startX * 100 + startY);
    				while (!queue.isEmpty()) {
    					int x = queue.peek() / 100;
    					int y = queue.poll() % 100;
    					int nxtCost = f[x][y] + 1;
    
    					for (int i = 0; i < 4; ++ i) {
    						int xx = x + dx[i];
    						int yy = y + dy[i];
    						if (xx >= 0 && xx < N && yy >= 0 && yy < m && empty(xx, yy) && f[xx][yy] > nxtCost) {
    							f[xx][yy] = nxtCost;
    							queue.offer(xx * 100 + yy);
    						}
    					}
    					if (trans(x, y) != -1) {
    						int y1 = trans(x, y);
    						if (f[x][y1] > nxtCost) {
    							f[x][y1] = nxtCost;
    							queue.offer(x * 100 + y1);
    						}
    					}
    				}
    				for (int i = 0; i <= n; ++ i) {
    					for (int j = 0; j < m; ++ j) {
    						d[sy][sx][j][i] = f[i + MAX_EXTENDED * n][j];
    					}
    				}
    			}
    		}
    	}
    
    }
    

      

  • 相关阅读:
    Python-22-并发编程
    hadoop学习记录(二)HDFS java api
    hadoop学习记录(一)HDFS
    hadoop学习记录(零)
    android 下载instagram动态中图片的demo
    android 使用<merge>标签
    利用dijkstra算法规划线路
    Android Studio如何引用外部Library工程
    设计模式(二):单例模式
    设计模式(一):设计模式入门
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/7856365.html
Copyright © 2011-2022 走看看