Codeforces Beta Round #23

acm_cxlove發表於2013-08-14

轉載請註明出處,謝謝http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

http://codeforces.com/contest/23

水了一天,做場CF。。。。發現是如此地弱

A:You are given a string

暴力列舉,要是閒著蛋疼就寫個SA什麼的吧。。。或者HASH一下。


B:Party

答案是max (0 , n - 2)

首先不可能一個點都不刪

也不可能只刪一個點(n >= 2)。假設只刪一個點,刪掉的點度數為d,那麼剩下所有點度數至少d + 1。

那麼刪掉這個點之後,對於剩下的點度數必須減少。那麼d = n - 1。不滿足剩下點度數至少為d + 1。

所以至少要刪兩個點,就可以構造了。

完全圖,刪掉一條邊之後,兩個點的度為n - 2 , 剩下點度數為n - 1。刪掉兩個點之後,剩下點度數為n - 3,不會再刪。


C:Oranges and Apples

深深地感覺到智商有多低。。。。

按蘋果數目排序,然後分為兩類,一種是隻取標號為奇數的,一種是取標號為偶數的以及最後一個。

容易得到這兩種情況都滿足蘋果至少有一半,那麼桔子的個數,哪種情況多就採用哪用。容易得到,必然有解。


D:Tetragon

假設四邊形四個點是a , b , c , d。中點為k , l , m分別為ab , bc , cd的中點。

那麼作m點關於l點的對稱點m‘,容易得到m’b = bl = bk ,所以b是三角形klm’的外心。

那麼剩下點就可以求出,然後 判斷下ab = bc = cd是否成立,以及用叉積判斷下是否為凸包

import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		int t = in.nextInt();
		Task solver = new Task();
		while ((t --) > 0)
			solver.solve(in, out);
		out.close();
	}
}
class Task{
	public double sqr (double d) {
		return d * d;
	}
	class Point {
		public double x , y;
		Point () {}
		Point (double _x , double _y) {
			x = _x;
			y = _y;
		}
		public double dist (Point a) {
			return sqr (x - a.x) + sqr (y - a.y);
		}
		public Point sym (Point a) {
			return new Point (x * 2 - a.x , y * 2 - a.y);
		}
		public Point circumcenter (Point a , Point b) {
			double a1 = b.x - a.x , b1 = b.y - a.y , c1= (a1 * a1 + b1 * b1) / 2.0;
			double a2 = x - a.x , b2 = y - a.y , c2 = (a2 * a2 + b2 * b2) / 2.0;
			double d = a1 * b2 - a2 * b1;
			return new Point (a.x + (c1 * b2 - c2 * b1) / d , a.y + (a1 * c2 - a2 * c1) / d);
		}
	}
	double xmul (Point p , Point p1 , Point p2) {
		return (p.x - p1.x) * (p.y - p2.y) - (p.y - p1.y) * (p.x - p2.x);
	}
	boolean equal (double a , double b) {
		double d = a - b;
		if (d < 0) d = -d;
		if (d < (1e-10)) return true;
		return false;
	} 
	boolean check (Point a , Point b , Point c , Point d) {
		double t1 = xmul (a , b , c) , t2 = xmul (b , c , d) , t3= xmul (c , d , a) , t4 = xmul (d , a , b);
		if (t1 * t2 <= 1e-5 || t2 * t3 <= 1e-5 || t3 * t4 <= 1e-5 || t4 * t1 <= 1e-5) return false;
		return true;
	}
	boolean gao (Point k , Point l , Point m , PrintWriter cout) {
		if (xmul(k , l , m) == 0) return false;
		Point b =k.circumcenter(l.sym(m) , l) , a = k.sym(b) , c = l.sym(b) , d = m.sym(c);
		if (!equal (a.dist(b) , b.dist(c)) || !equal(b.dist(c) , c.dist(d))) return false;		
		if (!check (a , b , c , d)) return false;
		cout.println("YES");
		cout.println(a.x + " " + a.y + " " + b.x + " " + b.y + " " + c.x + " " + c.y + " " + d.x + " " + d.y);
		return true;
	}
	void solve (InputReader cin , PrintWriter cout) {
		Point k , l , m;
		double x , y;
		x = cin.nextDouble();y=cin.nextDouble();
		k = new Point (x , y);
		x = cin.nextDouble();y=cin.nextDouble();
		l = new Point (x , y);
		x = cin.nextDouble();y=cin.nextDouble();
		m = new Point (x , y);
		if (gao (k , l , m , cout)) return ;
		if (gao (k , m , l , cout)) return ;
		if (gao (l , k , m , cout)) return ;
		if (gao (l , m , k , cout)) return ;
		if (gao (m , k , l , cout)) return ;
		if (gao (m , l , k , cout)) return ;
		cout.println("NO");
	}
}
class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;
    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }
    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }
    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong() {
    	return Long.parseLong(next());
    }
    public double nextDouble() {
    	return Double.parseDouble(next());
    }
    public BigInteger nextBigInteger() {
    	return new BigInteger(next());
    }
}

E:Tree

dp[i][j]表示以i為根的子樹,結點i所在連通塊結點個數為j的最大乘積。

tree dp的時候轉移兩種,一種是孩子節點與當前節點合併,一種是不合並。

由於題目要求高精度,偷懶用了java,然後n ^ 3的DP一直TLE。。。。

只能加些優化 了。。。

在合併的時候dp[u][j] / j  * dp[v][k] / k * (j + k) ,比較好理解,這裡有幾次除法,太耗時了。

所以我們考慮在dp[i][j]的時候,結果不記錄i節點所在連通塊,也就是dp[i][j] * j才是原來的結果。

那麼轉移的時候也不用除了,最後找答案的時候再乘上就OK了。

就這樣卡過去了。。。。。

import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		int t = 1;
		Task solver = new Task();
		while ((t --) > 0)
			solver.solve(in, out);
		out.close();
	}
}
class Task{
	static int N = 705;
	int size[] = new int[N];
	Vector edge[] = new Vector[N];
	BigInteger dp[][] = new BigInteger[N][N];
	static int n;
	BigInteger max (BigInteger a , BigInteger b) {
		return a.max(b);
	}
	void dfs (int u , int pre) {
		size[u] = 1;
		dp[u][1] = BigInteger.ONE;
		for (int i = 0 ; i < edge[u].size() ; i ++) {
			int v = (int)edge[u].elementAt(i);
			if (v == pre) continue;
			dfs (v , u);
			size[u] += size[v];
			BigInteger tmp[] = new BigInteger[N];
			BigInteger mx = BigInteger.ZERO;
			for (int k = 1 ; k <= size[v] ; k ++)
				mx = max (mx , dp[v][k].multiply(BigInteger.valueOf(k)));
			for (int j = 1 ; j <= size[u]  ; j ++) {
				tmp[j] = dp[u][j].multiply(mx);
			}
			for (int j = size[u] ; j >= 1 ; j --) {
				for (int k = 1 ; k < j && k <= size[v] ; k ++) {
					if (dp[u][j - k].equals(BigInteger.ZERO) || dp[v][k].equals(BigInteger.ZERO)) continue;
					dp[u][j] = max (dp[u][j] , dp[u][j - k].multiply(dp[v][k]));
				}
			}
			for (int j = 1 ; j <= size[u] ; j ++) {
				dp[u][j] = max (dp[u][j] , tmp[j]);
			}
		}
	}
	void solve (InputReader cin , PrintWriter cout) {
		n = cin.nextInt();
		for (int i = 1 ; i <= n ; i ++) {
			edge[i] = new Vector();
		}
		for (int i = 1 ; i < n ; i ++) {
			int u = cin.nextInt() , v = cin.nextInt();
			edge[u].addElement(v);
			edge[v].addElement(u);
		}
		for (int i = 1 ; i <= n ; i ++)
			for (int j = 1 ; j <= n ; j ++)
				dp[i][j] = BigInteger.ZERO;
		dfs (1 , -1);
		BigInteger ans = BigInteger.valueOf(n);
		for (int i = 1 ; i <= n ; i ++) {
			ans = max (ans , dp[1][i].multiply(BigInteger.valueOf(i)));
		}
		cout.println(ans);
	}
}
class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;
    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }
    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }
    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong() {
    	return Long.parseLong(next());
    }
    public double nextDouble() {
    	return Double.parseDouble(next());
    }
    public BigInteger nextBigInteger() {
    	return new BigInteger(next());
    }
}





相關文章