Gemini Boy - ACM之路~
随想
还有47天就是南京现场赛了。凭心而论,压力很大,现在天天只能睡5,6个小时,就要爬起来坐到电脑前做题。当然这不能怪别的,只能怪自己在过去的一年多没有好好练,挖的坑太大,可能没有时间填坑了。但是既然努力了1年多了,就不想在这最后的几十天留下遗憾。
列一下ToDoList(自己之前搞的不错的东西就不列出来了):
1.动态规划
- 数位DP
- 树形DP
- 状态压缩
2.数据结构
- 树套树
- CDQ分治
- 树链剖分
- 动态树
3.字符串
- AC自动机
- 后缀数组
- hash
- 后缀自动机
4.图论
- 网络流
- 连通分量
5.数学
- 高斯消元
- 概率与期望
- 组合数学
- 线性方程
要做的一些比赛:
POI 15-19th
Andrew Stankevich Contest 1-10
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=31687#overview
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=31688#overview
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=31294#overview
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=31535#overview
...(未完待续)
数位统计
19th Polish Olympiad in Informatics
链接:http://main.edu.pl/en/archive/oi/19
Festival(Stage I):
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <vector> #include <stack> using namespace std; const int maxn = 1000; const int inf = 1000000000; struct Edge { int v, w; Edge() {} Edge(int vv, int ww) { v = vv; w = ww; } }; vector<Edge> adj[maxn*2]; int idx, size; int n, m1, m2, a, b; int dist[maxn][maxn]; int dfn[maxn], low[maxn], stk[maxn], id[maxn]; bool vis[maxn]; stack<int> S; inline int Myabs(int x) { if (x < 0) x = -x; return x; } void addEdge(int u, int v, int w) { adj[u].push_back(Edge(v, w)); } void tarjan(int u) { dfn[u] = low[u] = ++idx; S.push(u); vis[u] = true; vector<Edge>::iterator it; for (it = adj[u].begin(); it != adj[u].end(); it++) { int v = it->v; if (dfn[v] == -1) { tarjan(v); low[u] = min(low[u], low[v]); } else if (vis[v]) { low[u] = min(low[u], dfn[v]); } } if (low[u] == dfn[u]) { size++; int v; do { v = S.top(); S.pop(); id[v] = size; vis[v] = false; } while (u != v); } } void clearAll() { for (int i = 0; i < maxn; i++) adj[i].clear(); memset(dfn, -1, sizeof(dfn)); memset(low, -1, sizeof(low)); memset(vis, false, sizeof(vis)); memset(id, 0, sizeof(id)); memset(dist, 0, sizeof(dist)); while (!S.empty()) S.pop(); } void init() { scanf("%d %d %d", &n, &m1, &m2); for (int i = 0; i < m1; i++) { scanf("%d %d", &a, &b); addEdge(a, b, 1); addEdge(b, a, -1); } for (int i = 0; i < m2; i++) { scanf("%d %d", &a, &b); addEdge(a, b, 0); } void work() { for (int i = 1; i <= n; i++) { if (dfn[i] == -1) tarjan(i); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (i == j) dist[i][j] = 0; else dist[i][j] = -inf; } } for (int i = 1; i <= n; i++) { vector<Edge>::iterator it; for (it = adj[i].begin(); it != adj[i].end(); it++) { int j = it->v; if (id[i] == id[j]) dist[i][j] = max(dist[i][j], it->w); } } for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { if (dist[i][k] <= -inf) continue; for (int j = 1; j <= n; j++) { if (dist[k][j] <= -inf) continue; if (dist[i][k] + dist[k][j] > dist[i][j]) dist[i][j] = dist[i][k] + dist[k][j]; } } } for (int i = 1; i <= n; i++) { if (dist[i][i] > 0) { puts("NIE"); return ; } } int result = 0; vector<int> ans; memset(vis, false, sizeof(vis)); for (int i = 1; i <= n; i++) { ans.clear(); if (vis[i] == true) continue; for (int j = 1; j <= n; j++) { if (id[i] == id[j]) { vis[j] = true; ans.push_back(j); } } int tmp = 0; for (int j = 0; j < ans.size(); j++) { for (int k = 0; k < ans.size(); k++) { tmp = max(tmp, Myabs(dist[ans[j]][ans[k]])+1); } } result += tmp; } printf("%d\n", result); } int main() { clearAll(); init(); work(); return 0; }
Letters(Stage I):
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> #include <vector> using namespace std; const int maxn = 1001000; char str1[maxn], str2[maxn]; vector<int> adj1[maxn], adj2[maxn]; int len, sum[maxn], pos[maxn]; int main() { scanf("%d %s %s", &len, str1, str2); for (int i = 0; i < len; i++) { adj1[str1[i]-'A'].push_back(i); adj2[str2[i]-'A'].push_back(i); } for (int i = 0; i < 26; i++) { for (int j = 0; j < adj1[i].size(); j++) { pos[adj1[i][j]] = adj2[i][j]; } } long long ans = 0; for (int i = len - 1; i >= 0; i--) { for (int j = pos[i]; j; j -= j & -j) ans += sum[j]; for (int j = pos[i] + 1; j <= len; j += j & -j) sum[j]++; } printf("%lld\n", ans); return 0; }
2013 ACM/ICPC Asia Regional Online —— Warmup
A题(HDU 4706):无意义的题,就贴个代码吧
#include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <iostream> using namespace std; void get(int x, int n) { int y = x + 2 * (n - 1); y %= 26; for (int i = 1; i <= n; i++) { printf("%c", 'a'+(x+i-1)%26); for (int j = n-i-1; j >= 1; j--) printf(" "); if (i > 1 && i < n) printf("%c", 'a'+(y+1-i+26)%26); for (int j = 1; j <= i-2; j++) printf(" "); printf("%c\n", 'a'+(y+i-1)%26); } } int main() { int x = 0; for (int i = 3; i <= 10; i++) { get(x, i); x = (x+2*i+i-2) % 26; } return 0; }
2012 Asia Chengdu Regional Contest
A题(HDU 4464):无意义的题。。就贴个代码吧。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; const int maxn = 10010; int n, cas; char ch[maxn]; int main() { cas = 0; while (~scanf("%d", &n)) { int ans = 0; for (int i = 0; i < n; i++) { scanf("%s", ch); int len = strlen(ch); int sum = 0; for (int i = 0; i < len; i++) { sum += (int)ch[i]; } if (ans < sum) ans = sum; } printf("Case %d: %d\n", ++cas, ans); } return 0; }
B题(HDU 4465):这题是道求期望的题,还算比较简单。公式很容易得到:
但是因为组合数比较大,不能直接算。为了保证精度,可以先求log,然后再用乘方,算回来。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cstring> #include <cmath> using namespace std; int n, cas = 0; double p; int main() { while (~scanf("%d %lf", &n, &p)) { printf("Case %d: ", ++cas); double q = 1 - p; if (fabs(p) < 1e-10 || fabs(q)<1e-10) { printf("%.6lf\n", 1.0 * n); continue; } double tmp = (n + 1) * log(p); double tem = (n + 1) * log(q); double ans = 0, t = 0, tt = 0, ttt = 0; for (int i = n + 1; i <= n + n; i++) { tt = t + tmp + (i-1-n) * log(q) + log(1.0+n+n-i); ttt = t + tem + (i-1-n) * log(p) + log(1.0+n+n-i); ans += exp(tt) + exp(ttt); t += log(1.0*i) - log(1.0*i-n); } printf("%.6lf\n", ans); } return 0; }