Codeforces Round #328 (Div. 2)
这场CF,准备充足,回寝室洗了澡,睡了一觉,可结果。。。
第一次忘记判断相等时A先走算A赢,hack掉。后来才知道自己的代码写错了(摔
for (int i=1; i<=8; ++i) { scanf ("%s", s[i]); //!!! }
数学(找规律) B - The Monster and the Squirrel
题意:多边形每个顶点向其它的点引射线,如果碰到其他射线则停止,问最后多边形被分成多少个区域
分析:搬题解:
Problem B. The monster and the squirrel
After drawing the rays from the first vertex (n - 2) triangles are formed. The subsequent rays will generate independently sub-regions in these triangles. Let's analyse the triangle determined by vertices 1, i, i + 1, after drawing the rays from vertex i and (i + 1) the triangle will be divided into (n - i) + (i - 2) = n - 2 regions. Therefore the total number of convex regions is (n - 2)2
If the squirrel starts from the region that have 1 as a vertex, then she can go through each region of triangle (1, i, i + 1) once. That implies that the squirrel can collect all the walnuts in (n - 2)2 jumps.
我一直在猜结论,试了一些公式,但和3,4的情况对不上。(卒
注意爆int
题意:两个在比赛,每个人的速度固定,终点<=t,问两人不分胜负的可能情况
分析:分类讨论,如果LCM (b, w) <= t, 那么每个LCM的倍数的点以及之后跟着的min (b, w) - 1都是不分胜负的,其他情况不详细分析。。。
注意的是LCM可能爆long long,可以先除和t比较或者转换成double log函数比较
/************************************************ * Author :Running_Time * Created Time :2015/10/31 星期六 22:41:05 * File Name :C.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const double EPS = 1e-10; const double PI = acos (-1.0); ll GCD(ll a, ll b) { return b ? GCD (b, a % b) : a; } int main(void) { ll t, w, b; scanf ("%I64d%I64d%I64d", &t, &w, &b); if (w > b) swap (w, b); if (w > t && b > t) { printf ("1/1\n"); } else if (b > t) { ll x = GCD (w - 1, t); printf ("%I64d/%I64d\n", (w - 1) / x, t / x); } else if (log ((double) w) + log ((double) b) - log ((double) GCD (w, b)) > log ((double) t)) { ll x = GCD (w - 1, t); printf ("%I64d/%I64d\n", (w - 1) / x, t / x); } else { ll lcm = b / GCD (w, b) * w; if (t % lcm == 0) { ll y = (w - 1) + (t / lcm - 1) * w + 1; ll x = GCD (y, t); printf ("%I64d/%I64d\n", y / x, t / x); } else { ll y = (w - 1) + (t / lcm - 1) * w + (1 + min (t % lcm, w - 1)); ll x = GCD (y, t); printf ("%I64d/%I64d\n", y / x, t / x); } } //cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n"; return 0; }
虚树的直径 D - Super M
题意:一棵树,有若干个点要走,问从哪个点出发可以使得路径最短,走完不用走回起点
分析:如果回到起点的话就是路径上的边的两倍,不回起点就减去一条最长的回路(直径)。首先找出包含所有要走的点的子树,从任意一点DFS找深度最大的点再DFS一遍,这样就可以找到直径,最后贪心找字典序小的直径的端点
/************************************************ * Author :Running_Time * Created Time :2015/10/31 星期六 22:41:05 * File Name :D.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 123456 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const double EPS = 1e-10; const double PI = acos (-1.0); bool mark[N]; int d[N]; int cnt[N]; vector<int> G[N]; void DFS(int u, int fa) { cnt[u] = 0; if (mark[u]) cnt[u] = 1; for (int v, i=0; i<G[u].size (); ++i) { v = G[u][i]; if (v == fa) continue; d[v] = d[u] + 1; DFS (v, u); cnt[u] += cnt[v]; } } int main(void) { int n, m; scanf ("%d%d", &n, &m); for (int u, v, i=1; i<n; ++i) { scanf ("%d%d", &u, &v); G[u].push_back (v); G[v].push_back (u); } int id = -1; for (int u, i=1; i<=m; ++i) { scanf ("%d", &u); mark[u] = true; if (id == -1 || id > u) { id = u; } } if (m == 1) { printf ("%d\n0\n", id); return 0; } DFS (1, 0); id = -1; for (int i=1; i<=n; ++i) { if (mark[i] && (id == -1 || d[id] < d[i])) { id = i; } } int es = 0, len = 0; memset (d, 0, sizeof (d)); DFS (id, 0); //从深度最深的点开始搜 for (int i=1; i<=n; ++i) { if (cnt[i] > 0 && m - cnt[i] > 0) { //这个cnt数组记录了以i为根的子树中被攻击的城市的个数 es += 2; } if (mark[i]) len = max (len, d[i]); } for (int i=1; i<=n; ++i) { //找到直径后取id小的端点 if (mark[i] && i < id && d[i] == len) { id = i; break; } } printf ("%d\n%d\n", id, es - len); //cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n"; return 0; }