2023杭电第七场补题报告1002 1004 1011 1013
1002 B. Random Nim Game (hdu.edu.cn)
思路
手推一下就可以发现其实除了一次必定结束的其他情况概论都是 1 2 \frac{1}{2} 21
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve();
signed main(){cin.sync_with_stdio(0);cin.tie(0);int T = 1;cin >> T;while(T--){solve();}return 0;
}void solve(){int n;cin >> n;int cn1 = 0;for(int i = 0;i < n;i++){int x;cin >> x;if(x > 1)cn1++;}if(cn1 == 0){if(n & 1){cout << "1\n";}else{cout << "0\n";}}else{cout << "499122177\n";}
}
1004 D. Medians Strike Back (hdu.edu.cn)
思路
若答案是 B,则构造为 {1, 3, 1*,* 3*, . . . ,* 1*,* 3*,* 2*,* 2*,* 1*,* 3*, . . .* },即 B 个 1 3 之后 2 2 构成一循环。**
代码
#include <bits/stdc++.h>
#define re register
using namespace std;
inline int read()
{re int t = 0;re char v = getchar();while (v < '0')v = getchar();while (v >= '0')t = (t << 3) + (t << 1) + v - 48, v = getchar();return t;
}
int t, n, ans;
int main()
{t = read();while (t--){n = read();re int l = 1, r = n;while (l <= r){re int mid = l + r >> 1, tmp = n / (mid + mid + 2);re int s = tmp * 2 + max(0, n % (mid + mid + 2) - mid - mid);if (s <= mid)ans = mid, r = mid - 1;elsel = mid + 1;}printf("%d\n", ans);}
}
1011 K. Three Operations (hdu.edu.cn)
思路
思考一下就会发现,直接选择收敛速度最快的进行,然后再在不选择最后两种情况的时候直接把当前数字加到结果中加速模拟。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc secondusing namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n;
int a[N];void solve() {int x, y;cin >> n >> x >> y;int res = 0;while (n != 0) {int x1 = n - 1, x2 = (n + x) / 2, x3 = sqrt(1.0 * (n + y));if(x2 >= n && x3 >= n){res += n;break;}if (x1 == min({x1, x2, x3}))n = x1;else if (x2 == min({x1, x2, x3}))n = x2;elsen = x3;res++;}cout << res << "\n";
}signed main() {IOS;int t = 1;cin >> t;for (int i = 1; i <= t; i++) {solve();}
}
1013 M. Minimal and Maximal XOR Sum (hdu.edu.cn)
思路
任选一个长度为 k 的区间,将其翻转,然后可以再利用 f(k) = k(k 2 −1) 次交换相邻两个数的操作再将这个区间翻转回去,相当于什么操作都没有做,而却多了一个权值为 k 的操作和 f(k) 个权值为 2 的操作,所以:
• 如果 k ≡ 0 (mod 4) 或 k ≡ 1 (mod 4),则我们可以任何时候将答案(权值异或和)异或 k;
• 如果 k ≡ 0 (mod 4) 或 k ≡ 1 (mod 4),则我们可以任何时候将答案异或 k ⊕ 2。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int read() {char c = getchar();int x = 0, s = 1;while (c < '0' || c > '9') {if (c == '-') s = -1;c = getchar();} //是符号while (c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();} //是数字return x * s;
}void solve();
signed main() {int T;T = read();while (T--) {solve();}return 0;
}
class FenwickTree {private:vector<int> tree;int n;public:FenwickTree(int size) {n = size;tree.resize(n + 1, 0);}// 单点更新:将索引i位置上的值增加valvoid update(int i, int val) {i++; // 树状数组的索引从1开始,所以将i加1while (i <= n) {tree[i] += val;i += lowbit(i);}}// 区间查询:计算前缀和,返回索引i位置的前缀和int query(int i) {i++; // 树状数组的索引从1开始,所以将i加1int sum = 0;while (i > 0) {sum += tree[i];i -= lowbit(i);}return sum;}// 区间查询:计算区间[i, j]的和int query(int i, int j) { return query(j) - query(i - 1); }private:int lowbit(int x) { return x & -x; }
};
void solve() {int n;n = read();vector<int> a(n + 1);for (int i = 1; i <= n; i++) {a[i] = read();}if (n == 1) {cout << "0 1\n";return;}FenwickTree t(n + 1);int cnt = 0;for (int i = 1; i <= n; i++) {cnt += t.query(a[i], n);t.update(a[i], 1);}// cout << cnt << "\n";int ans1 = 0, ans2 = 0;if (cnt & 1) {ans1 = 2;int c = log2(n) + 1;ans2 = (1 << c) - 1;} else {ans1 = 0;int c = log2(n) + 1;ans2 = (1 << c) - 1;ans2 -= 2;}cout << ans1 << " " << ans2 << "\n";
}