*注意:这套题目应版权方要求,不得公示题面。
表示十分怀疑出题人水平,C题数据和标程都是错的。有原题,差评。
Problem A XOR
题目大意
最小异或生成树
出门左拐Codeforces 888G。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <vector> 5 #ifndef WIN32 6 #define Auto "%lld" 7 #else 8 #define Auto "%I64d" 9 #endif 10 using namespace std; 11 typedef bool boolean; 12 #define ll long long 13 14 const int Mask = 1 << 30; 15 const signed int inf = (signed) (~0u >> 1); 16 17 typedef class TrieNode { 18 public: 19 TrieNode* ch[2]; 20 }TrieNode; 21 22 TrieNode pool[3300000]; 23 TrieNode* top; 24 25 TrieNode* newnode() { 26 top->ch[0] = top->ch[1] = NULL; 27 return top++; 28 } 29 30 typedef class Trie { 31 public: 32 TrieNode* rt; 33 34 void reset() { 35 top = pool; 36 rt = newnode(); 37 } 38 39 void insert(int x) { 40 TrieNode* p = rt; 41 int mask = Mask; 42 while (mask) { 43 int c = ((x & mask) ? (1) : (0)); 44 if (!p->ch[c]) 45 p->ch[c] = newnode(); 46 p = p->ch[c], mask >>= 1; 47 } 48 } 49 50 int query(int x) { 51 TrieNode* p = rt; 52 int mask = Mask, rt = 0; 53 while (mask) { 54 int c = ((x & mask) ? (1) : (0)); 55 if (p->ch[c]) 56 p = p->ch[c]; 57 else 58 p = p->ch[c ^ 1], rt += mask; 59 mask >>= 1; 60 } 61 return rt; 62 } 63 }Trie; 64 65 int n; 66 int* ar; 67 Trie tr; 68 69 inline void init() { 70 scanf("%d", &n); 71 ar = new int[(n + 1)]; 72 for (int i = 1; i <= n; i++) 73 scanf("%d", ar + i); 74 } 75 76 ll dividing(int tem, vector<int>& vs) { 77 if (!tem) 78 return 0; 79 vector<int> v0, v1; 80 for (int i = 0; i < (signed) vs.size(); i++) 81 if (vs[i] & tem) 82 v1.push_back(vs[i]); 83 else 84 v0.push_back(vs[i]); 85 if (!v0.size()) 86 return dividing(tem >> 1, v1); 87 if (!v1.size()) 88 return dividing(tem >> 1, v0); 89 tr.reset(); 90 for (int i = 0; i < (signed) v0.size(); i++) 91 tr.insert(v0[i]); 92 int rt = inf; 93 for (int i = 0, cmp; i < (signed) v1.size(); i++) { 94 cmp = tr.query(v1[i]); 95 rt = min(cmp, rt); 96 } 97 return rt * 1ll + dividing(tem >> 1, v0) + dividing(tem >> 1, v1); 98 } 99 100 inline void solve() { 101 vector<int> vs; 102 for (int i = 1; i <= n; i++) 103 vs.push_back(ar[i]); 104 printf(Auto, dividing(Mask, vs)); 105 } 106 107 int main() { 108 freopen("A.in", "r", stdin); 109 freopen("A.out", "w", stdout); 110 init(); 111 solve(); 112 return 0; 113 }
Problem B GCD
题目大意
最小gcd生成树,点权1~n。
加速Kruskal的过程。边排序的时候把编号也作为关键字。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 using namespace std; 5 typedef bool boolean; 6 7 int n; 8 9 inline void init() { 10 scanf("%d", &n); 11 } 12 13 int *uf; 14 15 int find(int x) { 16 return (uf[x] == x) ? (x) : (uf[x] = find(uf[x])); 17 } 18 19 long long res = 0; 20 inline void solve() { 21 uf = new int[(n + 1)]; 22 for (int i = 1; i <= n; i++) 23 uf[i] = i; 24 for (int i = n >> 1; i; i--) { 25 for (int j = i << 1; j <= n; j += i) { 26 if (find(i) != find(j)) { 27 res += i; 28 uf[find(i)] = find(j); 29 } 30 } 31 } 32 cout << res << endl; 33 } 34 35 int main() { 36 freopen("B.in", "r", stdin); 37 freopen("B.out", "w", stdout); 38 init(); 39 solve(); 40 return 0; 41 }
Problem C SEG
题目大意
平面的三角剖分。问边数的奇偶性。
mmp,最开始理解错题意了。是说咋觉得不可做。
可以求出凸包,设凸包上的点数和边数均为$m$。然后设顶点总数为$V$,边数为$E$,分割成的三角形的个数为$x$。
则根据欧拉公式有:$x + 1 + V - \frac{3x + m}{2} = 2$
解得:$x = 2n - m - 2$,由此得到边数。
另外这道题数据似乎对极角序不是很友好。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <cmath> 6 #ifndef WIN32 7 #define Auto "%lld" 8 #else 9 #define Auto "%I64d" 10 #endif 11 using namespace std; 12 typedef bool boolean; 13 14 #define ll long long 15 16 typedef class Point { 17 public: 18 ll x, y; 19 20 Point(ll x = 0.0, ll y = 0.0):x(x), y(y) { } 21 22 boolean operator < (Point b) const { 23 if (x ^ b.x) 24 return x < b.x; 25 return y < b.y; 26 } 27 }Point, Vector; 28 29 Point operator - (Point a, Point b) { 30 return Point(a.x - b.x, a.y - b.y); 31 } 32 33 ll cross(Point a, Point b) { 34 return a.x * b.y - a.y * b.x; 35 } 36 37 int n, m; 38 Point* ps; 39 40 inline void init() { 41 scanf("%d", &n); 42 ps = new Point[(n + 1)]; 43 for (int i = 1; i <= n; i++) 44 scanf(Auto""Auto, &ps[i].x, &ps[i].y); 45 } 46 47 int st; 48 Point* tp; 49 50 inline void solve() { 51 tp = new Point[(n + 2)]; 52 sort(ps + 1, ps + n + 1); 53 for (int i = 1; i <= n; i++) { 54 while (st > 1 && cross(tp[st] - tp[st - 1], ps[i] - tp[st]) <= 0) 55 st--; 56 tp[++st] = ps[i]; 57 } 58 m += st - 2, st = 0; 59 for (int i = n; i; i--) { 60 while (st > 1 && cross(tp[st] - tp[st - 1], ps[i] - tp[st]) <= 0) 61 st--; 62 tp[++st] = ps[i]; 63 } 64 m += st; 65 66 int A = ((n << 1) - m) - 2; 67 int E = (3 * A + m) >> 1; 68 if (E & 1) 69 puts("Alice"); 70 else 71 puts("Bob"); 72 } 73 74 int main() { 75 init(); 76 solve(); 77 return 0; 78 }