NOIP模拟测试19
数据好水,暴力干翻正解(((
Problem A: count
一个能被分成大小为k的联通块,必定满足k | n。预处理每个子树大小,枚举n的因子。
我本来以为是树形DP,但颓不出来柿子Orz,把暴力交了结果A了。。
这个做法很容易被卡到T飞:一个长度有巨多因子的链就可以做到。但数据真的很水。。。。
1 #include <bits/stdc++.h> 2 3 const int N = 20000005; 4 int n, ans, ecnt; 5 int siz[N], head[N]; 6 struct Edge {int to, nxt;} e[N << 1]; 7 8 inline int read() { 9 int a = 0; char c = getchar(); 10 while (!isdigit(c)) c = getchar(); 11 while (isdigit(c)) a = a * 10 + c - '0', c = getchar(); 12 return a; 13 } 14 15 inline void addEdge(int f, int to) { 16 e[++ecnt] = {to, head[f]}, head[f] = ecnt; 17 e[++ecnt] = {f, head[to]}, head[to] = ecnt; 18 } 19 20 void dfs(int x, int fa) { 21 siz[x] = 1; 22 for (int i = head[x], y = e[i].to; i; i = e[i].nxt, y = e[i].to) { 23 if (y != fa) { 24 dfs(y, x); 25 siz[x] += siz[y]; 26 } 27 } 28 } 29 30 signed main() { 31 n = read(); 32 for (int i = 1; i < n; i++) { 33 int x = read(), y = read(); 34 addEdge(x, y); 35 } 36 dfs(1, 0); 37 for (int i = 1; i <= n; i++) { 38 if (n % i == 0) { 39 int tmp = 0; 40 for (int j = 1; j <= n; j++) { 41 if (siz[j] % i == 0) tmp++; 42 } 43 if (tmp == n / i) ans++; 44 } 45 } 46 return !printf("%d\n", ans); 47 }
Problem B: dinner
破环为链,找出这条链上长度为n的一段
裸暴力是N^3的,考虑优化,我写了二分套二分,加一点比较tricky的小剪枝。
正确性其实我是不敢确定的,因为我也没证。但WA了总比T了好(逃
1 #include <bits/stdc++.h> 2 3 int n, m, mx, sum; 4 int t[100005], pre[100005]; 5 6 inline int read() { 7 int a = 0; char c = getchar(); 8 while (!isdigit(c)) c = getchar(); 9 while (isdigit(c)) a = a * 10 + c - '0', c = getchar(); 10 return a; 11 } 12 13 bool check(int x) { 14 for (int i = n + 1, tot = 0; i >= 1 && tot + t[i] <= x; tot += t[i--]){ 15 int p = i - 1, div = 0; 16 while (p < i + n - 1) { 17 int l = p + 1, r = i + n - 1, mid, ans; 18 while (l <= r) { 19 mid = (l + r) >> 1; 20 if (pre[mid] - pre[p] <= x) 21 ans = mid, l = mid + 1; 22 else r = mid - 1; 23 } 24 p = ans; 25 ++div; 26 if (div > m) break; 27 } 28 if (p == i + n - 1 && div <= m) return true; 29 } 30 return false; 31 } 32 33 signed main() { 34 n = read(), m = read(); 35 for (int i = 1; i <= n; i++) { 36 t[i] = read(), t[i + n] = t[i]; 37 sum += t[i]; 38 mx = std::max(mx, t[i]); 39 } 40 for (int i = 1; i <= 2 * n; i++) 41 pre[i] = pre[i - 1] + t[i]; 42 int l = mx, r = sum, mid, ans = 0; 43 while (l <= r) { 44 mid = (l + r) >> 1; 45 if (check(mid)) r = mid - 1, ans = mid; 46 else l = mid + 1; 47 } 48 return !printf("%d\n", ans); 49 }
Problem C: chess
考场5min敲了个DFS骗10分,性价比真高啊(
正解:建图跑最短路计数。
但题目中有个条件:两条路径只有经过的空格有不一样才能被认为是不同的。
于是就出现零环的问题,它没用。
怎么解决?我们扫一遍图,对于权值为1的点dfs一遍去连边,这样可以避免零环,连出有效的边。
这题数据锅了,这个做法当时只有70pt。。。换数据后就能A了XD
1 #include <bits/stdc++.h> 2 #define id(x, y) ((x - 1) * m + y) 3 4 const int N = 300003; 5 const int dx[8] = {-2, -2, -1, -1, 1, 1, 2, 2}; 6 const int dy[8] = {-1, 1, -2, 2, -2, 2, -1, 1}; 7 int n, m, st, ed; 8 long long dis[N], cnt[N]; 9 int matrix[505][505], mp[2505][2505]; 10 bool vis[N]; 11 std::vector<int> v; 12 13 inline int read() { 14 int a = 0; char c = getchar(); 15 while (!isdigit(c)) c = getchar(); 16 while (isdigit(c)) a = a * 10 + c - '0', c = getchar(); 17 return a; 18 } 19 20 void dfs(int x, int y) { 21 vis[id(x, y)] = 1; 22 for (int i = 0; i <= 7; i++) { 23 int xx = x + dx[i], yy = y + dy[i]; 24 if (xx < 1 || yy < 1 || xx > n || yy > n || vis[id(xx, yy)]) continue; 25 if (matrix[xx][yy] != 1 && matrix[xx][yy] != 2) { 26 v.push_back(id(xx, yy)); 27 vis[id(xx, yy)] = 1; 28 } else if (matrix[xx][yy] == 1) dfs(xx, yy); 29 } 30 } 31 32 void bfs() { 33 memset(dis, 0x3f, sizeof(dis)); 34 dis[st] = 0, cnt[st] = 1; 35 std::queue<int> q; 36 q.push(st); 37 while (!q.empty()) { 38 int x = q.front(); 39 q.pop(); 40 for (int i = 1; i <= n * m; i++) { 41 if (mp[x][i]) { 42 if (dis[i] > dis[x] + 1) { 43 if (dis[i] == 0x3f3f3f3f3f3f3f3f) q.push(i); 44 dis[i] = dis[x] + 1; 45 cnt[i] = cnt[x]; 46 } else if (dis[i] == dis[x] + 1) cnt[i] += cnt[x]; 47 } 48 } 49 } 50 } 51 52 signed main() { 53 n = read(), m = read(); 54 for (int i = 1; i <= n; i++) { 55 for (int j = 1; j <= m; j++) { 56 matrix[i][j] = read(); 57 if (matrix[i][j] == 3) st = id(i, j); 58 if (matrix[i][j] == 4) ed = id(i, j); 59 } 60 } 61 for (int i = 1; i <= n; i++) { 62 for (int j = 1; j <= m; j++) { 63 if (matrix[i][j] == 1 && !vis[id(i, j)]) { 64 dfs(i, j); 65 for (int x = 0; x < v.size(); x++) { 66 for (int y = x + 1; y < v.size(); y++) { 67 mp[v[x]][v[y]] = mp[v[y]][v[x]] = 1; 68 } 69 } 70 for (auto x : v) vis[x] = 0; 71 v.clear(); 72 } 73 } 74 } 75 for (int i = 1; i <= n; i++) { 76 for (int j = 1; j <= m; j++) { 77 if (matrix[i][j] == 1 || matrix[i][j] == 2) continue; 78 for (int k = 0; k <= 7; k++) { 79 int x = i + dx[k], y = j + dy[k]; 80 if (x < 1 || y < 1 || x > n || y > m) continue; 81 if (matrix[x][y] == 2 || matrix[x][y] == 1) continue; 82 mp[id(i, j)][id(x, y)] = mp[id(x, y)][id(i, j)] = 1; 83 } 84 } 85 } 86 bfs(); 87 if (dis[ed] == 0x3f3f3f3f3f3f3f3f) { 88 puts("-1"); 89 } else { 90 printf("%lld\n%lld\n", dis[ed] - 1, cnt[ed]); 91 } 92 return 0; 93 }
$ \Theta \omega \Theta $