Codeforces Round #684 (Div. 2) 11/17
技術標籤:Codeforces題解
T1
中文題意:
T組輸入,每次第一行輸入4個整數
n
,
c
0
,
c
1
,
h
n,c_0,c_1,h
n,c0,c1,h,第二行給出一個長度為n的二進位制串。你可以花費h把它某一位取反。最終你要花
c
0
c_0
c0買下全部的0,
c
1
c_1
c1買下全部的1,問最小的花費是多少。
T
≤
10
,
n
,
c
0
,
c
1
,
h
≤
1
0
3
T\leq10,n,c_0,c_1,h\leq10^3
T≤10,n,c0,c1,h≤103
簡單思維,換掉一位一定是花費更少才會換,那麼這個換了花費更少,那就把全部0都要換掉或者1換掉。所以總結,要麼全換1 or 0,或者一次都不換。
void solve() {
ll n = read(), c0 = read(), c1 = read(), h = read();
char s[1005];
scanf("%s", s);
ll ans = 0;
ll cnt0 = 0, cnt1 = 0;
for (int i = 0; i < n; ++i)
if (s[i] == '0') ++cnt0;
else ++cnt1;
if (c0 >= c1 + h)
ans = cnt0 * h + n * c1;
else if (c1 >= c0 + h)
ans = cnt1 * h + n * c0;
else
ans = cnt1 * c1 + cnt0 * c0;
print(ans);
}
T2
中文題意:
T組輸入,每組輸入第一行輸入n,k,第二行有
n
∗
k
n*k
n∗k個數。你要把這些數分隔成k組,每組n個元素,問這k組資料的中位數和最大是多少?
T
≤
100
,
1
≤
n
,
k
≤
1
0
3
,
a
i
≤
1
0
9
T\leq100,1\leq n,k\leq10^3,a_i\leq10^9
T≤100,1≤n,k≤103,ai≤109。
簡單思維,按照下面的放法會求得全部數中位數最大,按照從小打到排序後,每次取後面沒取的
⌈
n
2
⌉
\lceil\frac{n}{2}\rceil
const int N = 1e5 + 7;
int n, m;
int a[1000005];
void solve() {
ll ans = 0;
n = read(), m = read();
for (int i = 1; i <= n * m; ++i) a[i] = read();
sort(a + 1, a + 1 + n * m);
int pos = m * ((n + 1 >> 1) - 1) + 1;
int len = n - (n + 1 >> 1) + 1;
while (m--) ans += a[pos], pos += len;
print(ans);
}
T3
中文題意:
T組輸入,每組輸入第一行n,m代表矩陣規模,接著給出一個01矩陣,你每次可以選擇
2
∗
2
2*2
2∗2的小矩陣,翻轉其中的3個元素,0變1,1變0,如果限制你最多可以操作的次數為
3
∗
n
∗
m
3*n*m
3∗n∗m,要你輸出你選擇的方案操作次數k,以及k次操作具體反轉了哪3個點。
T
≤
5000
,
2
≤
n
,
m
≤
100
T\leq5000,2\leq n,m\leq100
T≤5000,2≤n,m≤100。
模擬題,觀察發現我們可以檢測每一個矩陣,我們找到矩陣中1的變化規律是。
4
→
1
→
2
→
3
→
0
4\to1\to2\to3\to0
4→1→2→3→0,這裡給的
3
∗
n
∗
m
3*n*m
3∗n∗m很大,觀察發現遍歷即可,難點在C4。
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op) putchar(op); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); if (op) putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 100 + 7;
int n, m, mp[N][N];
struct Node {
int x[3], y[3];
int cnt;
}ans[3 * N * N];
int tot;
int calc(int x, int y) {
return mp[x][y] + mp[x + 1][y] + mp[x][y + 1] + mp[x + 1][y + 1];
}
void push(int pos, int i, int j) {
ans[pos].x[ans[pos].cnt] = i;
ans[pos].y[ans[pos].cnt] = j;
++ans[pos].cnt;
}
void check(int x, int y) {
int tmp = calc(x, y);
if (tmp == 0) return;
if (tmp == 4) {
push(tot, x, y);
push(tot, x + 1, y);
push(tot, x, y + 1);
++tot;
mp[x][y] = mp[x + 1][y] = mp[x][y + 1] = 0;
tmp = 1;
}
if (tmp == 1) {
int flag = 0;
for (int i = x; i <= x + 1; ++i)
for (int j = y; j <= y + 1; ++j) {
if (mp[i][j] == 1) {
mp[i][j] = 0;
push(tot, i, j);
}
else if (flag < 2) {
mp[i][j] = 1;
push(tot, i, j);
++flag;
}
}
++tot;
tmp = 2;
}
if (tmp == 2) {
int flag0 = 0, flag1 = 0;
for (int i = x; i <= x + 1; ++i)
for (int j = y; j <= y + 1; ++j) {
if (mp[i][j] == 1 and flag1 == 0) {
mp[i][j] = 0;
push(tot, i, j);
++flag1;
}
else if (mp[i][j] == 0 and flag0 < 2) {
mp[i][j] = 1;
push(tot, i, j);
++flag0;
}
}
++tot;
tmp = 3;
}
if (tmp == 3) {
for (int i = x; i <= x + 1; ++i)
for (int j = y; j <= y + 1; ++j) {
if (mp[i][j] == 1) {
mp[i][j] = 0;
push(tot, i, j);
}
}
++tot;
}
}
void print(Node& ans) {
printf("%d %d ", ans.x[0], ans.y[0]);
printf("%d %d ", ans.x[1], ans.y[1]);
printf("%d %d\n", ans.x[2], ans.y[2]);
}
void solve() {
n = read(), m = read();
char s[N];
for (int i = 1; i <= n; i++) {
scanf("%s", s + 1);
for (int j = 1; j <= m; j++) {
mp[i][j] = s[j] - '0';
}
}
tot = 0;
for (int i = 0; i < 3 * N * N; ++i) ans[i].cnt = 0;
for (int i = 1; i < n; i++)
for (int j = 1; j < m; j++) {
check(i, j);
}
print(tot);
for (int i = 0; i < tot; i++)
print(ans[i]);
}
int main() {
int T = 1;
T = read();
while (T--) {
solve();
}
return 0;
}
T4
題意與上題幾乎一致,但是把限制
k
≤
3
∗
n
∗
m
k\leq 3*n*m
k≤3∗n∗m改為了
k
≤
n
∗
m
k\leq n*m
k≤n∗m。
4
→
1
→
2
→
3
→
0
4\to1\to2\to3\to0
4→1→2→3→0,每個矩陣最多花費4步,如果行列是偶數的話,剛好可以分完矩陣,所以
k
≤
n
∗
m
k\leq n*m
k≤n∗m成立,如果是奇數的話我們要處理最後一行或者最後一列全部先為0,接著上面偶數的方法,假設
n
,
m
n,m
n,m都是奇數,方法步驟是
k
≤
n
+
1
2
+
m
+
1
2
+
(
n
−
1
)
∗
(
m
−
1
)
k\leq \frac{n+1}{2}+\frac{m+1}{2} + (n-1)*(m-1)
k≤2n+1+2m+1+(n−1)∗(m−1),這樣就符合了k的要求了。
)這個大模擬題目挺有意思收錄了。
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
#define rep(i, sta, en) for(int i=sta; i<=en; ++i)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op) putchar(op); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); if (op) putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 100 + 7;
int n, m, mp[N][N];
struct Node {
int x[3], y[3];
int cnt;
}ans[N * N];
int tot;
int calc(int x, int y) {
return mp[x][y] + mp[x + 1][y] + mp[x][y + 1] + mp[x + 1][y + 1];
}
void push(int pos, int i, int j) {
ans[pos].x[ans[pos].cnt] = i;
ans[pos].y[ans[pos].cnt] = j;
++ans[pos].cnt;
}
void check(int x, int y) {
int tmp = calc(x, y);
if (tmp == 0) return;
if (tmp == 4) {
push(tot, x, y);
push(tot, x + 1, y);
push(tot, x, y + 1);
++tot;
mp[x][y] = mp[x + 1][y] = mp[x][y + 1] = 0;
tmp = 1;
}
if (tmp == 1) {
int flag = 0;
for (int i = x; i <= x + 1; ++i)
for (int j = y; j <= y + 1; ++j) {
if (mp[i][j] == 1) {
mp[i][j] = 0;
push(tot, i, j);
}
else if (flag < 2) {
mp[i][j] = 1;
push(tot, i, j);
++flag;
}
}
++tot;
tmp = 2;
}
if (tmp == 2) {
int flag0 = 0, flag1 = 0;
for (int i = x; i <= x + 1; ++i)
for (int j = y; j <= y + 1; ++j) {
if (mp[i][j] == 1 and flag1 == 0) {
mp[i][j] = 0;
push(tot, i, j);
++flag1;
}
else if (mp[i][j] == 0 and flag0 < 2) {
mp[i][j] = 1;
push(tot, i, j);
++flag0;
}
}
++tot;
tmp = 3;
}
if (tmp == 3) {
for (int i = x; i <= x + 1; ++i)
for (int j = y; j <= y + 1; ++j) {
if (mp[i][j] == 1) {
mp[i][j] = 0;
push(tot, i, j);
}
}
++tot;
}
}
void check1(int x, int y) { // 處理奇數最後一列
int tmp = calc(x, y);
if (!tmp) return;
if (tmp == 2) {
push(tot, x, y), mp[x][y] = 0;
push(tot, x + 1, y), mp[x + 1][y] = 0;
push(tot, x, y - 1), mp[x][y - 1] ^= 1;
++tot;
}
else {
if (mp[x][y]) push(tot, x, y), mp[x][y] = 0;
else push(tot, x + 1, y), mp[x + 1][y] = 0;
push(tot, x, y - 1), mp[x][y - 1] ^= 1;
push(tot, x + 1, y - 1), mp[x + 1][y - 1] ^= 1;
++tot;
}
}
void check2(int x, int y) { // 處理奇數最後一行
int tmp = calc(x, y);
if (!tmp) return;
if (tmp == 2) {
push(tot, x, y), mp[x][y] = 0;
push(tot, x, y + 1), mp[x][y + 1] = 0;
push(tot, x - 1, y), mp[x - 1][y] ^= 1;
++tot;
}
else {
if (mp[x][y]) push(tot, x, y), mp[x][y] = 0;
else push(tot, x, y + 1), mp[x][y + 1] = 0;
push(tot, x - 1, y), mp[x - 1][y] ^= 1;
push(tot, x - 1, y + 1), mp[x - 1][y + 1] ^= 1;
++tot;
}
}
void print(Node& ans) {
printf("%d %d ", ans.x[0], ans.y[0]);
printf("%d %d ", ans.x[1], ans.y[1]);
printf("%d %d\n", ans.x[2], ans.y[2]);
}
void solve() {
n = read(), m = read();
char s[N];
for (int i = 1; i <= n; i++) {
scanf("%s", s + 1);
for (int j = 1; j <= m; j++) {
mp[i][j] = s[j] - '0';
}
}
tot = 0;
for (int i = 0; i < N * N; ++i) ans[i].cnt = 0;
if (n % 2 == 1 and m % 2 == 1) {
check2(n, m - 1); // 把n,m點變成0
for (int i = 1; i < n; i += 2)
check1(i, m);
for (int i = 1; i < m; i += 2)
check2(n, i);
}
else if (n % 2) {
for (int i = 1; i < m; i += 2)
check2(n, i);
}
else {
for (int i = 1; i < n; i += 2)
check1(i, m);
}
for (int i = 1; i < n; i += 2)
for (int j = 1; j < m; j += 2) {
check(i, j);
}
print(tot);
for (int i = 0; i < tot; i++)
print(ans[i]);
}
int main() {
int T = 1;
T = read();
while (T--) {
solve();
}
return 0;
}