转载请注明出处,谢谢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());
}
}