A
map.
B
emulate.
C
$9! = 362800$,不是很大,枚举所有可能的观察序列然后 check。
具体来说打个时间戳然后挨个检查是否出现了题中的情况。
// Enonya
#include <bits/stdc++.h>
using namespace std;
int a[10], od[10], vis[4][4];
vector<pair<int, int>> v;
int id(int x, int y) {
return (y + (x - 1) * 3);
}
int main() {
v.clear(), v.push_back({0, 0});
for(int i = 1; i <= 9; ++i) od[i] = i;
for(int i = 1; i <= 3; ++i) {
for(int j = 1; j <= 3; ++j) {
cin >> a[id(i, j)];
v.push_back({i, j});
}
}
int ans = 0, cur = 0;
do {
++cur;
for(int i = 1; i <= 9; ++i) {
int x = v[od[i]].first, y = v[od[i]].second;
vis[x][y] = i;
}
bool flag = false;
for(int i = 1; i <= 3; ++i) {
int mx = max(vis[i][1], max(vis[i][2], vis[i][3]));
if(a[id(i, 1)] == a[id(i, 2)]) {
if(vis[i][3] == mx) {
flag = true; break;
}
}
if(a[id(i, 2)] == a[id(i, 3)]) {
if(vis[i][1] == mx) {
flag = true; break;
}
}
if(a[id(i, 3)] == a[id(i, 1)]) {
if(vis[i][2] == mx) {
flag = true; break;
}
}
}
for(int j = 1; j <= 3; ++j) {
int mx = max(vis[1][j], max(vis[2][j], vis[3][j]));
if(a[id(1, j)] == a[id(2, j)]) {
if(mx == vis[3][j]) {
flag = true; break;
}
}
if(a[id(2, j)] == a[id(3, j)]) {
if(mx == vis[1][j]) {
flag = true; break;
}
}
if(a[id(3, j)] == a[id(1, j)]) {
if(mx == vis[2][j]) {
flag = true; break;
}
}
}
int mx = max(vis[1][1], max(vis[2][2], vis[3][3]));
if(a[id(1, 1)] == a[id(2, 2)] && vis[3][3] == mx) flag = true;
if(a[id(2, 2)] == a[id(3, 3)] && vis[1][1] == mx) flag = true;
if(a[id(3, 3)] == a[id(1, 1)] && vis[2][2] == mx) flag = true;
mx = max(vis[1][3], max(vis[2][2], vis[3][1]));
if(a[id(1, 3)] == a[id(2, 2)] && vis[3][1] == mx) flag = true;
if(a[id(2, 2)] == a[id(3, 1)] && vis[1][3] == mx) flag = true;
if(a[id(3, 1)] == a[id(1, 3)] && vis[2][2] == mx) flag = true;
if(flag == true) ans++;
} while(next_permutation(od + 1, od + 10));
ans = cur - ans;
cout << fixed << setprecision(10) << (long double)ans / (long double)cur << endl;
return 0;
}
看官方题解有更快一点的写法,就是存一个 vector<array<int, 3>>
表示一下每一行每一列还有对角线的一维坐标,这样子能大幅减少代码量。
做的时候第一次没读懂题的意思就开做然后写错,写代码的时候 od[i]
错写成 i
,甚至最后才发现概率是 without disappointment
...
哎复健
D
手玩一下立马可以发现答案具有单调性,注意到答案的范围 $10^9$,但是判定的复杂度可以是 $O(n)$ 的,所以二分答案。
可行区间在左边,写二分主体的时候要注意一下:
// Enonya
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int si = 2e5 + 10;
const int inf = 1e18;
int n, m, a[si], s[si];
int leng(int l, int r) {
if(l > r) return inf;
return (s[r] - s[l - 1]) + (r - l);
}
bool valid(int v) {
int l = 1, r = 1, tot = 0;
while(l <= r && r <= n) {
if(leng(l, r) > v) return false;
if(leng(l, r + 1) > v) {
tot++, l = r + 1, r = r + 1;
}
else r++;
}
return tot <= m;
}
signed main() {
cin >> n >> m, s[0] = 0;
for(int i = 1; i <= n; ++i) {
cin >> a[i], s[i] = s[i - 1] + a[i];
}
s[n + 1] = inf;
int ans = 0;
int l = 1, r = inf, mid;
while(l < r) {
mid = (l + r) >> 1;
if(valid(mid)) r = mid, ans = mid;
else l = mid + 1;
}
cout << ans << endl;
return 0;
}
l + r >> 1
的话永远不会取到 $r$ 的初值所以一般是将 $r$ 设置为真实上界 + 1 以判定无解,自然适用于可行区间在左的情况
(l + r + 1) >> 1
则永远不会取到 $l$ 的初值。
记得开一下 long long
。
E
咕咕咕。
Copyright @Enonya, 转载请注明出处