Codeforces Round #250 (Div. 2)

最近学了python,决定拿这套Chinese Round(vfk一伙人出的)练练手。太弱,只能拿div 2练,囧。

link

A - The Child and Homework

很有中国特色的一题。

算法

考你会不会编程。

代码

a = sorted([(len(input()) - 2, i) for i in 'ABCD'])
p = 0
if a[0][0] * 2 <= a[1][0]:
    p += 1
if a[-2][0] * 2 <= a[-1][0]:
    p += 2
print(['C', a[0][1], a[-1][1], 'C'][p])

B - The Child and Set

算法

贪心即可。

代码

target, limit = map(int, input().split())

def lowbit(x):
    return x & (x ^ (x - 1))

ans = []
for i in range(limit, 0, -1):
    x = lowbit(i)
    if x <= target:
        ans.append(i)
        target -= x

if target:
    print(-1)
else:
    print(len(ans))
    print(" ".join(map(str, ans)))

C - The Child and Toy

算法

贪心即可。

我们可以从消去边的角度来看。那么消去一条边((u,v))的代价是(cost[u])(cost[v]),我们肯定选最少的那个。这样我们便给每条边定了一个方向,变成了有向图。
如果这个图是DAG那么我们就能全部消去了,且花费一定是最少的。但如果有环就不行了。事实上是没有环的,如果有环a->b->c->...->a,就会出现(x < y, y < z, z < x)这种不科学的事情。

代码

read = lambda: map(int, input().split())
n, m = read()
cost = list(read())

ans = 0
for i in range(m):
    v, u = read()
    ans += min(cost[v - 1], cost[u - 1])
print(ans)

D - The Child and Zoo

算法

考虑某个点作为多少个路径的最小点。

然后最小生成树统计即可。

代码

read = lambda: map(int, input().split())
n, m = read()
v = list(read())

e = []
for i in range(m):
    x, y = map(lambda x: int(x) - 1, input().split())
    e.append((x, y, min(v[x], v[y])))
e.sort(key = lambda x: x[2], reverse = True)

belong = list(range(n))
union = [[i] for i in belong]
size = [1] * n

ans = 0

for i, j, k in e:
    fi, fj = belong[i], belong[j];
    if fi == fj: continue
    if not (len(union[fi]) > len(union[fj])):
        fi, fj = fj, fi
    ans += k * size[fi] * size[fj]
    size[fi] += size[fj]
    union[fi] += union[fj]
    for t in union[fj]: belong[t] = fi
    
print("%.7lf" % (ans * 2 / n / (n - 1)))

E - The Child and Polygon

算法

直接DP就好。
这题python过不了,而且除了我没有人用python写,囧。

我服了python(O(8000000))的算法,(2s)TLE

而且这题我还不会调试,用输出中间变量的方法弄了很久才过样例。QAQ

代码

class point:
    def __init__(self, a, b):
        self.x, self.y = a, b

def cross(a, b):
    return a.x * b.y - a.y * b.x

def rePoint(a, b):
    return point(a.x - b.x, a.y - b.y)

n = int(input())
a = []
for i in range(n):
    x, y = map(int, input().split())
    a.append(point(x, y))
a.append(a[0])

area = 0
for i in range(n):
    area += cross(a[i], a[i + 1])
if area < 0:
    a = a[::-1]

mod = 10**9 + 7

#dp = [[0] * n] * n  不要用这个,什么浅复制,坑人啊
dp = [[0] * n for i in range(n)]

for l in range(1, n):
    for i in range(n):
        j = i + l
        if j >= n: break
        if l == 1:
            dp[i][j] = 1;
            continue
        else:
            for k in range(i + 1, j):
                if cross(rePoint(a[i], a[j]), rePoint(a[k], a[j])) > 0:
                    dp[i][j] += dp[i][k] * dp[k][j]
                    dp[i][j] %= mod

print(dp[0][-1])

以伟大的c++代码结束这一题:

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;

typedef long long i64;

const int MAXN = 203;
const int MOD = (int) 1e9 + 7;

struct Point {
	int x, y;

	Point(int _x = 0, int _y = 0) :
		x(_x), y(_y) {}

	i64 operator * (const Point &o) const {
		return (i64) x * o.y - (i64) y * o.x;
	}

	Point operator - (const Point &o) const {
		return Point(x - o.x, y - o.y);
	}
};

int n;
Point A[MAXN];

int main() {
	scanf("%d", &n);
	for (int i = 0; i < n; i ++) 
		scanf("%d%d", &A[i].x, &A[i].y);
	i64 area = 0;
	A[n] = A[0];
	for (int i = 0; i < n; i ++)
		area += A[i] * A[i + 1];
	if (area < 0) reverse(A, A + n);

	static i64 dp[MAXN][MAXN];

	for (int len = 1; len < n; len ++)
		for (int i = 0; i < n; i ++) {
			int j = i + len;
			if (j >= n) break;
			if (len == 1) {
				dp[i][j] = 1;
				continue;
			}
			for (int k = i + 1; k < j; k ++) {
				if ((A[i] - A[j]) * (A[k] - A[j]) > 0) {
					dp[i][j] += dp[i][k] * dp[k][j];
					dp[i][j] %= MOD;
				}
			}
		}
	cout << dp[0][n - 1] << endl;
	return 0;
}

总结

不是水题不要用python!不是水题不要用python!不是水题不要用python!不是水题不要用python!不是水题不要用python

python写水题很爽!python写水题很爽!python写水题很爽!python写水题很爽!python写水题很爽!python写水题很爽!

原文地址:https://www.cnblogs.com/wangck/p/4394343.html