题意: 游戏大模拟 题解: 模拟 代码:
#include <bits/stdc++.h> using namespace std; const int N = 6; const int SEED = 31; int a[N][N]; int m; set<uint64_t> f; struct Car { bool is_vertical; int lx, ly, rx, ry; // or upos dpos Car() : lx(INT_MAX), ly(INT_MAX), rx(0), ry(0) {} } p[10 + 5]; struct Stat { int st[N][N]; void copy() { memcpy(st, a, sizeof(a)); } void paste() { memcpy(a, st, sizeof(a)); } Stat() { memset(st, 0, sizeof(st)); } }; uint64_t encode() { uint64_t seed = 0; for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) seed = (seed + a[i][j]) * SEED; return seed; } void init_car() { for (int i = 1; i <= m; ++i) p[i] = Car(); for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) { int x = a[i][j]; p[x].lx = min(p[x].lx, i); p[x].ly = min(p[x].ly, j); p[x].rx = max(p[x].rx, i); p[x].ry = max(p[x].ry, j); if (p[x].lx == p[x].rx) p[x].is_vertical = false; if (p[x].ly == p[x].ry) p[x].is_vertical = true; } } int bfs() { queue<pair<int, Stat> > que; Stat temp; temp.copy(); que.push(make_pair(0, temp)); while (!que.empty()) { int step = que.front().first; if (step > 8) { return -1; } if (a[2][5] == 1) { return step + 2; } temp = que.front().second; que.pop(); temp.paste(); uint64_t code = encode(); if (f.count(code)) continue; f.insert(code); init_car(); for (int t = 1; t <= m; ++t) { if (p[t].is_vertical) { int lx = p[t].lx; int rx = p[t].rx; int y = p[t].ly; if (0 < lx && a[lx - 1][y] == 0) { a[lx - 1][y] = t; a[rx][y] = 0; temp.copy(); que.push(make_pair(step + 1, temp)); a[rx][y] = t; a[lx - 1][y] = 0; } if (rx + 1 < N && a[rx + 1][y] == 0) { a[rx + 1][y] = t; a[lx][y] = 0; temp.copy(); que.push(make_pair(step + 1, temp)); a[lx][y] = t; a[rx + 1][y] = 0; } } else { int x = p[t].lx; int ly = p[t].ly; int ry = p[t].ry; if (0 < ly && a[x][ly - 1] == 0) { a[x][ly - 1] = t; a[x][ry] = 0; temp.copy(); que.push(make_pair(step + 1, temp)); a[x][ly - 1] = 0; a[x][ry] = t; } if (ry + 1 < N && a[x][ry + 1] == 0) { a[x][ry + 1] = t; a[x][ly] = 0; temp.copy(); que.push(make_pair(step + 1, temp)); a[x][ry + 1] = 0; a[x][ly] = t; } } } } return -1; } int main() { ios::sync_with_stdio(false); for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) { cin >> a[i][j]; m = max(a[i][j], m); } init_car(); cout << bfs() << endl; }题意: 签到 题解: 签到 代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; int const N = 2e5 + 10; int n, m, T, a[N]; int main() { cin >> n; for (int i = 1; i <=n ; ++i) cin >> a[i]; int flg = 1; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { for (int k = 1; k <= n; ++k) { if (i == j || i == k || j == k) continue; if ((a[i] - a[j]) % a[k] != 0) flg = 0; } } } if (flg) cout << "yes\n"; else cout << "no\n"; return 0; }题意: 签到 题解: 签到 代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; int const N = 2e5 + 10; int n, m, T, a[N]; string s1 = "tapioka", s2 = "bubble"; int main() { vector<string> res; string s; while(cin >> s) { if (s != s1 && s != s2) res.push_back(s); } if (res.empty()) cout << "nothing"; else { for (auto r: res) cout << r << " "; } return 0; }题意: 对于问题 m a x 1 < = l < = r < = n ( r − l + 1 ) ∑ l < = i < = r a i max_{1<=l<=r<=n}(r-l+1) \sum_{l<=i<=r}a_i max1<=l<=r<=n(r−l+1)∑l<=i<=rai 给定一段错误代码,输入一个k和l,要求构造出一个长度大于等于l的序列,使得错误代码和正确代码算出来的结果差的绝对值恰好为k。 给你一个k和l,k 题解: 观察错误代码错误的原因:错误代码要找到连续的子段,子段的和为正数,然后求出字段和乘上长度,一旦发现负数,那么就改变子段的左区间。而其实改变子段的左区间这个操作不对,可能导致子段的长度变小。因此构造的时候,就要让错误代码找出来的子段长度更小,正确代码找到子段长度更大一些。由于n最大只有1999,因此如果长度大于1999则无法找到答案。为了保证在长度小于等于1999时能够找到这样的合法序列,序列长度取1999.为了保证错误代码找到的子段长度更短,因此第一个数字取-1,这样:错误代码不取第一个,正确代码取第一个,就会导致计算出来的结果不一致。构造方式如下: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XB9TO4L2-1601731564497)(https://i.loli.net/2020/10/03/bLHDeod2mNI68tU.jpg)] 代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; int const N = 2e5 + 10; int k, l, T, a[N]; int main() { cin >> T; while(T--) { cin >> k >> l; if (l >= 2000) { cout << -1 << endl; continue; } int sum_suf = 1999 + k; cout << 1999 << endl; cout << -1 << " "; int avg = sum_suf / 1997; for (int i = 2; i <= 1998; ++i) { cout << avg << " "; } cout << sum_suf - avg * 1997 << endl; } return 0; }题意: 给定一个式子 1 n = 1 a x o r b + 1 b \frac{1}{n} = \frac{1}{a xor b} + \frac{1}{b} n1=axorb1+b1, 给定n,能够求出很多对(a, b)满足这个式子。要求给出最大的那个a。 题解: 推导如下: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rYaFSQNb-1601731564500)(https://i.loli.net/2020/10/03/DlT8pYMZL6AW34k.jpg)] 因此,枚举 n 2 n^2 n2的约数即可。 对于给定的异或的式子:
线性基位运算性质:把每一位隔开算异或没有,用其他式子转化,然后就能够得到很多形如 k + a b k+\frac{a}{b} k+ba的式子,a是一个确定值,那么枚举a的约数,或者质因数等方法代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; int const N = 2e5 + 10; int m, T, a[N]; LL n_2, n; int main() { cin >> T; while(T--) { scanf("%lld", &n); n_2 = n * n; vector<int> divisor; for (int i = 1; i <= n_2 / i; ++i) { // 枚举到sqrtx(x) if (n_2 % i == 0) { // 如果能够整除 divisor.push_back(i); // 放入i if (i != n_2 / i) divisor.push_back(n_2 / i); // x/i不等于i,也放入答案中 } } LL res = -1; int len = divisor.size(); for (int i = 0; i < len; ++i) { int d = divisor[i]; res = max(res, (n + d) ^ (n * n / d + n)); } printf("%lld\n", res); } return 0; }题意: 有n个物品,每个物品都有m个特征,问最少选择多少个物品,使得所有的特征都能够被选到。 题解: 由于本题物品的数目和特征的数目都非常小,因此直接dfs暴力枚举选择了哪些物品即可。 代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; int const N = 2e5 + 10; int n, m, T; bitset<600> a[N]; int res; void dfs(int u, bitset<600> now, int cnt) { if (now.count() == m) { res = min(res, cnt); return; } for (int i = u + 1; i <= n; ++i) { bitset<600> next_now = now | a[i]; dfs(i, next_now, cnt + 1); } return; } int main() { cin >> T; while(T--) { res = 1e9; scanf("%d%d", &m, &n); for (int i = 1; i <= n; ++i) { string s; cin >> s; a[i] = bitset<600> (s); } res = 1e9; dfs(0, 0, 0); if (res == 1e9) res = -1; printf("%d\n", res); } return 0; }题意: 合并果子签到题 题解: 签到 代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; int const N = 2e5 + 10; int n, m, T, a[N]; priority_queue<int, vector<int>, greater<int> > q; int main() { cin >> T; while(T--) { cin >> n; for (int i = 1; i <= n; ++i) { int t; cin >> t; q.push(t); } int res = 0; while(q.size()) { if (q.size() == 1) break; int t = q.top(); q.pop(); t += q.top(); res += t; q.pop(); q.push(t); } // res += q.top(); q.pop(); cout << res << endl; } return 0; }题意: 计算几何xxxxx 题解: 队友说是旋转卡壳xxxx,不懂,贴上队友代码 代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <vector> using namespace std; const int N = 5009; int T, n; typedef long long LL; struct point{ LL x, y; point(){} point(LL _x, LL _y):x(_x), y(_y){} bool operator < (point B)const{ if(x != B.x)return x < B.x; else return y < B.y; } LL operator * (point B)const{ return x * B.y - y * B.x; } point operator - (point B)const{ return point(x - B.x, y - B.y); } bool operator == (point B)const{ if(x == B.x && y == B.y)return true; else return false; } void input(){ scanf("%lld%lld", &x, &y); } }; vector<point> ConvexHull(vector<point> p){ vector<point>ch(n + 1);//必須使用後靜態,不然後面無法訪問(因爲其中并沒有pushback東西) sort(p.begin(), p.end()); p.erase(unique(p.begin(), p.end()), p.end()); int n = p.size(); int m = 0; for(int i = 0; i < n; i++) { while(m > 1 && (ch[m - 1]- ch[m - 2]) * (p[i] - ch[m - 2]) <= 0)//邊上可有點 m--; ch[m++] = p[i]; } int k = m; for(int i = n - 2; i >= 0; i--) { while(m > k && (ch[m - 1]- ch[m - 2])*(p[i] - ch[m - 2]) <= 0) m--; ch[m++] = p[i]; } if(n > 1)m--;//ch[m] = ch[0] ch.resize(m);//resize 不會初始化ch[0]...ch[m - 1] return ch; } typedef point Vector; vector<point>v1; LL solve(point U, point V){ vector<point>X; int flagu = 0, flagv = 0; for(auto p:v1){ if(p == U){ flagu++; if(flagu > 1)X.push_back(p); } else if(p == V){ flagv++; if(flagv > 1)X.push_back(p); } else X.push_back(p); } LL max1 = 0, max2 = 0, ans = 0, min1 = 1e18, min2 = 1e18; for(auto p:X){ LL tmp = (V - U) * (p - U); if(tmp > 0){ max1 = max(max1, tmp); min1 = min(min1, tmp); } else{ max2 = max(max2, abs(tmp)); min2 = min(min2, abs(tmp)); } LL q = 0; if(max1 == 0 || max2 == 0){ if(flagu > 1|| flagv > 1)q = max1 + max2; else q = max(max1 - min1, max2 - min2); } else q = max1 + max2; ans = max(ans, q); } return ans; }/* 計算面積的時候用叉乘沒有誤差,用距離計算會出現小數誤差! 這裏還要注意防備四邊形為只有對踵點一側的凹四邊形的情況 */ int main(){ cin >> T; while(T--){ cin >> n; v1.clear(); vector<point>B; for(int i = 0; i < n; i++){ point p; p.input(); v1.push_back(p); B.push_back(p); } B = ConvexHull(B); int m = B.size(); if(m <= 2){ printf("0\n"); continue; } int j = 1; LL ans = 0; for(int i = 0; i < m; i++){//優化旋轉卡殼 while(abs((B[i] - B[(j + 1) % m]) * (B[(i + 1) % m] - B[(j + 1) % m])) > abs((B[i] - B[j]) * (B[(i + 1) % m] - B[j])) ){ j = (j + 1) % m; } ans = max(ans, solve(B[i], B[j])); } if(ans & 1)printf("%lld.5\n", ans / 2); else printf("%lld\n", ans / 2); } return 0; } /* 繁體中文真刺激。。。 */