[题解]NOIP2014提高组の题解集合
来源:互联网 发布:软件迭代记录 编辑:程序博客网 时间:2024/06/12 00:01
Day 1
T1 rps
模拟题。根据
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}const int N = 205;int ac[5][5] = { {0, -1, 1, 1, -1}, {1, 0, -1, 1, -1}, {-1, 1, 0, -1, 1}, {-1, -1, 1, 0, 1}, {1, 1, -1, -1, 0}}, n, na, nb, cnt1, cnt2, a[N], b[N];int main() { //freopen("rps.in", "r", stdin); //freopen("rps.out", "w", stdout); int i; n = read(); na = read(); nb = read(); for (i = 1; i <= na; i++) a[i] = read(); for (i = 1; i <= nb; i++) b[i] = read(); for (i = 1; i <= n; i++) { int x = a[(i - 1) % na + 1], y = b[(i - 1) % nb + 1]; if (ac[x][y] == 1) cnt1++; else if (ac[x][y] == -1) cnt2++; } printf("%d %d\n", cnt1, cnt2); return 0;}
T2 link
考虑到
1、
2、
对于情况
对于情况
对于寻找最大值,找出
对于求和,先不考虑是否选了两个相同的子节点。
设
然后从
注意:1、最大值不要取模。2、合法点对
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}typedef long long ll;const int N = 2e5 + 5, PYZ = 10007;int n, tot, a[N], w[N], ecnt, nxt[N << 1], adj[N], go[N << 1], sum;ll mv;void add_edge(int u, int v) { nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v; nxt[++ecnt] = adj[v]; adj[v] = ecnt; go[ecnt] = u;}bool comp(int x, int y) { return w[x] < w[y];}void dfs(int u, int fu) { int i; tot = 0; ll res = 0, tmp = 0; for (int e = adj[u], v; e; e = nxt[e]) if ((v = go[e]) != fu) a[++tot] = v, res += w[v], tmp += 1ll * w[v] * w[v]; sort(a + 1, a + tot + 1, comp); ll tm = sum; (sum += ((res % PYZ) * (res % PYZ) - tmp % PYZ) % PYZ + PYZ) %= PYZ; if (tot >= 2) mv = max(mv, 1ll * w[a[tot - 1]] * w[a[tot]]); if (fu) { mv = max(mv, 1ll * w[fu] * w[a[tot]]); (sum += 2ll * w[fu] * res % PYZ) %= PYZ; } for (int e = adj[u], v; e; e = nxt[e]) if ((v = go[e]) != fu) dfs(v, u);}int main() { //freopen("link.in", "r", stdin); //freopen("link.out", "w", stdout); int i, x, y; n = read(); for (i = 1; i < n; i++) x = read(), y = read(), add_edge(x, y); for (i = 1; i <= n; i++) w[i] = read(); dfs(1, 0); cout << mv << " " << sum << endl; return 0;}
T3 bird
完全背包DP。设
边界为:
转移:
1、当
(即当高度达到
2、当
如果
否则
(即此操作上升)
3、当
(即此操作下降)
注意一些细节。
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}const int N = 1e4 + 5, M = 1005, INF = 0x3f3f3f3f;int n, m, K, X[N], Y[N], U[N], D[N], f[N][M];bool is[N];void chkmin(int &a, int b) {a = min(a, b);}int main() { //freopen("bird.in", "r", stdin); //freopen("bird.out", "w", stdout); int i, j, k, x, cnt = 0; n = read(); m = read(); K = read(); U[n] = m + 1; for (i = 0; i < n; i++) X[i] = read(), Y[i] = read(), U[i] = m + 1; for (i = 1; i <= K; i++) x = read(), D[x] = read(), U[x] = read(), is[x] = 1; for (i = 1; i <= n; i++) for (j = 0; j <= m + 1; j++) f[i][j] = INF; for (i = 1; i <= n; i++) { for (j = 0; j <= m; j++) { if (j == m) { for (k = 0; k <= m; k++) chkmin(f[i][j], f[i - 1][k] + ( k == m ? 1 : (j - k - 1) / X[i - 1] + 1)); continue; } if (j >= X[i - 1]) { if (j >= (X[i - 1] << 1)) chkmin(f[i][j], min(f[i - 1][j - X[i - 1]] + 1, f[i][j - X[i - 1]] + 1)); else chkmin(f[i][j], f[i - 1][j - X[i - 1]] + 1); } } for (j = 0; j <= m - Y[i - 1]; j++) chkmin(f[i][j], f[i - 1][j + Y[i - 1]]); for (j = 0; j <= D[i]; j++) f[i][j] = INF; for (j = U[i]; j <= m + 1; j++) f[i][j] = INF; if (is[i]) { bool flag = 0; for (j = D[i] + 1; j <= U[i] - 1; j++) if (f[i][j] < INF) {flag = 1; break;} if (flag) cnt++; } } int res = INF; for (j = 1; j <= m; j++) chkmin(res, f[n][j]); if (res < INF) printf("1\n%d\n", res); else printf("0\n%d\n", cnt); return 0;}
Day 2
T1 wireless
模拟题,暴力枚举每个区域即可。注意边界。
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}const int N = 134;int d, n, a[N][N];int check(int x, int y) { int i, j, x1, y1, x2, y2, ans = 0; x1 = max(0, x - d); y1 = max(0, y - d); x2 = min(128, x + d); y2 = min(128, y + d); for (i = x1; i <= x2; i++) for (j = y1; j <= y2; j++) ans += a[i][j]; return ans;}int main() { //freopen("wireless.in", "r", stdin); //freopen("wireless.out", "w", stdout); int i, j, tot = 0, ans = 0; d = read(); n = read(); for (i = 1; i <= n; i++) a[read()][read()] = read(); for (i = 0; i <= 128; i++) for (j = 0; j <= 128; j++) ans = max(ans, check(i, j)); for (i = 0; i <= 128; i++) for (j = 0; j <= 128; j++) tot += (check(i, j) == ans); printf("%d %d\n", tot, ans); return 0;}
T2 road
构造出一个原图和一个各边方向相反的反图。先在反图上从终点开始进行一遍DFS,标记出可以到达终点的点,再标记出路径上不能包含(即存在一个与其相邻的节点不能到达终点)的节点,然后SPFA即可。
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}const int N = 1e4 + 5, M = 2e5 + 5, INF = 0x3f3f3f3f;int n, m, ecnt, nxt[M], adj[N], go[M], ecnt2, nxt2[M], adj2[N], go2[M],que[M << 2], len, dis[N], S, T; bool vis[N], con[N], can[N];void add_edge(int u, int v) { nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v; nxt2[++ecnt2] = adj2[v]; adj2[v] = ecnt2; go2[ecnt2] = u;}void dfs(int u) { can[u] = 1; for (int e = adj2[u], v; e; e = nxt2[e]) if (!can[v = go2[e]]) dfs(v);}void mark() { memset(con, true, sizeof(con)); int i; for (i = 1; i <= n; i++) for (int e = adj[i]; e; e = nxt[e]) if (!can[go[e]]) {con[i] = 0; break;}}int spfa() { if (!con[S]) return -1; int i; memset(dis, INF, sizeof(dis)); dis[que[len = 1] = S] = 0; for (i = 1; i <= len; i++) { int u = que[i]; vis[u] = 0; for (int e = adj[u], v; e; e = nxt[e]) if (con[v = go[e]] && dis[u] + 1 < dis[v]) { dis[v] = dis[u] + 1; if (!vis[v]) vis[que[++len] = v] = 1; } } return dis[T] < INF ? dis[T] : -1;}int main() { //freopen("road.in", "r", stdin); //freopen("road.out", "w", stdout); int i, x, y; n = read(); m = read(); for (i = 1; i <= m; i++) x = read(), y = read(), add_edge(x, y); S = read(); T = read(); printf("%d\n", (dfs(T), mark(), spfa())); return 0;}
T3 equation
首先,考虑怎样解决高精度计算的复杂度问题。
可以想到取模。选
考虑继续优化。可以发现,对于任意整数
复杂度
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}const int N = 105, M = 1e4 + 5, MOD = 5e4 + 5;int PYZ[] = {10007, 25933, 27367, 38501, 41177}, n, m, val[N][7],sol[7][MOD];char s[M];int ModPYZ(int len, int pyz) { int i = 1 + (s[1] == '-'), ans = 0; for (; i <= len; i++) ans = (ans * 10 + s[i] - '0') % pyz; if (s[1] == '-') ans = pyz - ans; if (ans == pyz) ans = 0; return ans;}int solve(int x, int id) { int i, now = 1, ans = 0; for (i = 0; i <= n; i++, (now *= x) %= PYZ[id]) (ans += val[i][id] * now) %= PYZ[id]; return ans;}int main() { //freopen("equation.in", "r", stdin); //freopen("equation.out", "w", stdout); int i, j, l, cnt = 0; n = read(); m = read(); for (i = 0; i <= n; i++) { scanf("%s", s + 1); l = strlen(s + 1); for (j = 0; j < 5; j++) val[i][j] = ModPYZ(l, PYZ[j]); } for (i = 0; i < 5; i++) for (j = 0; j < PYZ[i]; j++) sol[i][j] = solve(j, i); for (i = 1; i <= m; i++) { bool flag = 1; for (j = 0; j < 5; j++) flag = flag && (sol[j][i % PYZ[j]] == 0); if (flag) cnt++; } printf("%d\n", cnt); for (i = 1; i <= m; i++) { bool flag = 1; for (j = 0; j < 5; j++) flag = flag && (sol[j][i % PYZ[j]] == 0); if (flag) printf("%d\n", i); } return 0;}
- [题解]NOIP2014提高组の题解集合
- NOIP2014提高组DAY1题解
- noip2014 提高组题解 equation
- noip2014 提高组题解 bird
- noip2014 提高组题解 link
- noip2014 提高组题解 road
- [题解]NOIP2015提高组の题解集合
- [题解]NOIP2016提高组の题解集合
- noip2014普及组题解
- noip2014提高组day2二题题解-rLq
- Noip2014题解
- NOIP2014题解
- NOIp2014 题解
- Noip2014寻找道路题解
- NOIP2014部分题解
- noip2014解方程题解
- [noip2014]寻找道路 题解
- [noip2014]解方程 题解
- php oauth2 微信授权登录
- JQuery动画总结
- Linux下mysql 5.6.17安装图文教程详细版
- 用XML写View的用法(一)——shape的用法
- Java反射机制深入详解
- [题解]NOIP2014提高组の题解集合
- Git Cheat Sheet
- 深度学习深理解(八)- 结构化机器学习项目
- Tomcat管理平台
- QT4.8.6和VS2010环境搭建
- StringUtils常用方法
- 那些年把我们坑惨的指针
- 接口回调
- 栈和队列的相互实现