Codeforces Round #150 (Div. 2)
A题 Dividing Orange
题目大意:有k个孩子,每个孩子要n个橘子,并且第i个孩子指定要一个橘子编号为ai的橘子,现在你有n*k个橘子,输出满足所有孩子的方案。
题解:模拟,我们先把每个孩子想要的橘子ai给他们,接着把那些还没有分出去的橘子给他们直到他们每个人都拥有n个橘子即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <vector> #include <queue> #include <stack> #include <cmath> #include <map> using namespace std; #define INF 0x73737373 #define EPS 1e-8 #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 map <int, int> c; bool vis[1005]; int main() { int n, k; scanf("%d%d", &n, &k); for(int i = 0; i < k; i++) { int a; scanf("%d", &a); c[i] = a; vis[a] = true; } int pos = 1; for(int i = 0; i < k; i++) { printf("%d ", c[i]); int num = 0; for(;;pos++) { if(!vis[pos]) { printf("%d ", pos); vis[pos] = true; num++; } if(num == n - 1)break; } printf("\n"); } return 0; }
B题 Undoubtedly Lucky Numbers
题目大意:定义一种数称为Undoubtedly Lucky Numbers,这种数是最多只由两个不同的数字组成的正整数,给一个上限n输出1-n的范围内有多少个这样的数。
题解:由于这种数最多只由两个不同的数组成,所以我们可以枚举这两个数字的在整个数中的出现位置,dfs即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <vector> #include <queue> #include <stack> #include <cmath> #include <map> using namespace std; #define INF 0x73737373 #define EPS 1e-8 #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 set <__int64> ret; int n, x, y; void dfs(__int64 num, int times) { if(num > n || times > 10)return; ret.insert(num); dfs(10 * num + x, times + 1); dfs(10 * num + y, times + 1); } int main() { scanf("%d", &n); for(x = 0; x < 10; x++) for(y = x + 1; y < 10; y++) dfs(0, 0); printf("%d\n", ret.size() - 1); return 0; }
C题 The Brand New Function
题目大意:给一个序列包含n个数,定义f(l, r)为连续区间l、r内所有数求或的结果,输出这个序列一共有多少个结果不同的f(l, r)
题解:因为操作是OR操作,所以,如果f(l, r)和f(l, r-1)的结果相同的话,那么f(x, r-1) 和f(x, r) (1<= x <= l)的结果肯定全部相同。
因此,我们可以枚举这个区间的右值r,然后往左遍历,一旦找到一个l,使得f(l, r) == f(l, r-1)就结束这次遍历,从而用比较少的时间求出所有结果。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <vector> #include <queue> #include <stack> #include <cmath> #include <map> using namespace std; #define INF 0x73737373 #define EPS 1e-8 #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 set <int> ret; int a[105000]; int main() { int n; scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%d", &a[i]); ret.insert(a[i]); int high = a[i], low = 0; for(int j = i - 1; j >= 0; j--) { high |= a[j]; low |= a[j]; ret.insert(high); if(high == low)break; } } printf("%d\n", ret.size()); return 0; }
D题 Hydra
题目大意:
定义一个九头蛇图,其中两个点u和v分别作为胸部和腹部,胸部会连着h个点作为头,腹部会连着t个点作为尾。
现在有一个无向图,让你确定其子图中是否存在一个九头蛇图。
题解:由于边数和点数都只有10W,所以用邻接表储存后直接暴力即可。
遍历所有点,选出度大于h的点vh作为头(因为要跟腹部相连,所以度应该大于h而不是大于等于h)
接着找跟vh相连并且度大于t的点vt作为腹部,因为一个点不可能又做头又做尾,所以只要检查一下当前的vh和vt是否合法即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <vector> #include <queue> #include <stack> #include <cmath> #include <map> using namespace std; #define INF 0x73737373 #define EPS 1e-8 #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 vector <int> edge[105000], head; bool vis[105000]; int n, m, h, t; bool solve(int hi, int ti) { int hnum = 0, tnum = 0; memset(vis, false, sizeof(vis)); for(int i = 0; i < edge[hi].size(); i++) if(edge[hi][i] != ti) { hnum++; vis[edge[hi][i]] = true; } for(int i = 0; i < edge[ti].size(); i++) if(edge[ti][i] != hi) if(!vis[edge[ti][i]]) tnum++; else if(hnum > h) { vis[edge[ti][i]] = false, tnum++, hnum--; } if(hnum >= h && tnum >= t) { puts("YES"); printf("%d %d\n", hi, ti); for(int i = 0; i < edge[hi].size() && h; i++) if(vis[edge[hi][i]]) { printf("%d ", edge[hi][i]); h--; } puts(""); for(int i = 0; i < edge[ti].size() && t; i++) if(!vis[edge[ti][i]] && edge[ti][i] != hi) { printf("%d ", edge[ti][i]); t--; } return true; } return false; } bool find() { for(int i = 0; i < head.size(); i++) for(int j = 0; j < edge[head[i]].size(); j++) { int hi = head[i]; int ti = edge[hi][j]; if(edge[ti].size() > t) if(solve(hi, ti)) return true; } return false; } int main() { scanf("%d%d%d%d", &n, &m, &h, &t); for(int i = 0; i < m; i++) { int a, b; scanf("%d%d", &a, &b); edge[a].push_back(b); edge[b].push_back(a); } for(int i = 1; i <= n; i++) if(edge[i].size() > h) head.push_back(i); if(!find()) puts("NO"); return 0; }