(6/6) AtCoder Beginner Contest 186

fujang發表於2020-12-24

(6/6) AtCoder Beginner Contest 186

A - Brick

題意:

有一個車最多可以裝N斤,一塊磚M斤,問最多可以裝多少磚。

思路:

N/M下取整。

程式碼:

#include <bits/stdc++.h>
using namespace std;

void work() {
	int a, b;
	cin >> a >> b;
	cout << a / b << endl;
}

int32_t main() {
	int cas;
	cas = 1;
	while (cas--) work();
}

B - Blocks on Grid

題意:

給你一個int陣列,每個陣列元素都可以減去若干值,問最少減去多少值可以使陣列元素全部相等。

思路:

找到最小元素,讓每個元素都等於最小元素。

程式碼:

#include <bits/stdc++.h>
using namespace std;
int a[101][101];
int mn = 101;
int res;

void work() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
			cin >> a[i][j];
			mn = min(a[i][j], mn);
		}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
			res += a[i][j] - mn;
		}
	cout << res << endl;
}

int32_t main() {
	int cas;
	cas = 1;
	while (cas--) work();
}

C - Unlucky 7

題意:

給你一個數N,問1到N中有多少個數的十進位制和八進位制的每一位都不含7。

思路:

列舉1到N,把每個數轉為十進位制和八進位制檢查統計。

程式碼:

#include <bits/stdc++.h>
using namespace std;
int res;

bool judge(int x) {
	vector<int> v;
	while (x) {
		v.push_back(x % 8);
		x /= 8;
	}
	for (int i = 0; i < v.size(); i++) {
		if (v[i] == 7) return 0;
	}
	return 1;
}

void work() {
	int n;
	cin >> n;
	int res = 0;
	for (int i = 1; i <= n; i++) {
		if (!judge(i)) continue;
		int x = i;
		int f = 0;
		while (x) {
			if (x % 10 == 7) f = 1;
			x /= 10;
		}
		if (f) continue;
		res++;
	}
	cout << res << endl;
}

int32_t main() {
	int cas;
	cas = 1;
	while (cas--) work();
}

D - Sum of difference

題意:

給你N個數,有正有負。
問每兩對的差的絕對值之和為多少,不重複,即i和j與j和i算一對。

思路:

從小到大排序,第一個數被減去n-1次,第二個數被減去n-3次,以此類推。
正-負=正,符合要求。
負-負=正,符合要求。
正-正=正,符合要求。

程式碼:

#include <bits/stdc++.h>
#define int long long
using namespace std;
int a[200010];

void work() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	sort(a + 1, a + n + 1);
	int res = 0;
	int k = -(n-1);
	for (int i = 1; i <= n; i++) {
		res += k * a[i];
		k += 2;
	}
	cout << res << endl;
}

int32_t main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int cas;
	cas = 1;
	while (cas--) work();
}

E - Throne

題意:

N個椅子圍成全,每次可以順勢針走K個,出發點在順時針離目標點S個位置上,求最少走幾次。

思路:

x K ≡ ( N − S ) m o d    N xK \equiv (N-S) \mod N xK(NS)modN 求最小的正整數x。
套線性同餘方程的板子。

程式碼:

#include <algorithm>
#include <iostream>
#define int long long
using namespace std;
typedef long long LL;

int exgcd(int a, int b, int &x, int &y) {
    if (!b) {
        x = 1, y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

int32_t main() {
    int t;
    cin >> t;
    while (t--) {
        int n, s, k;
        cin >> n >> s >> k;
        s = n - s;

        int x, y;
        int d = exgcd(k, n, x, y);
        if (s % d) puts("-1");
        else cout << ((int)(s / d * x) % (n / d) + n / d) % (n / d) << endl;
    }
    return 0;
}

F - Rook on Grid

題意:

給一個N*M的矩陣,N,M為2e5的資料。
矩陣中有K個障礙物,問從1,1的位置出發,兩步可以到達的所有位置的個數。

思路:


我們假設黑色的格子是障礙物,紅色的格子是不能到達的點。
那麼當一個點不能到達時,它左側同行必有一個格子為障礙物,它上側同列必有一個障礙物。
如果障礙物在第一列或者第一行出現,那麼這一列或這一行的後面都無法到達,都假設存在障礙物,我們增加障礙物的個數,但是記得去重。

我們假設灰色為增加的障礙物。
因此障礙物個數要開3*N大小的陣列。
所有我們列舉每一個障礙物,標記每個障礙物出現的列。
那麼存在障礙物的每一行中不能到達的點的個數為,從這一行第一個障礙物開始到這一行末尾的每一列標記列數之和,單點修改,區間查詢,可以考慮樹狀陣列實現。

程式碼:

#include <bits/stdc++.h>
#define int long long
#define lowbit(x) x & (-x)
using namespace std;
constexpr int maxn = 600010;
int tr[maxn];
bool vis[maxn];

struct Point {
	int x, y;
	bool operator < (const Point &W) const {
		if (x == W.x) return y < W.y;
		else return x < W.x;
	}
	
	bool operator == (const Point &W) const {
		return x == W.x && y == W.y;
	}
} p[maxn];

void add(int x, int n) {
	for (int i = x; i <= n; i += lowbit(i)) tr[i]++;
}

int query(int x) {
	int ans = 0;
	for (int i = x; i > 0; i -= lowbit(i)) ans += tr[i];
	return ans;
}

void work() {
	int H, W, M;
	cin >> H >> W >> M;
	int x_min = maxn, y_min = maxn;
	for (int i = 1; i <= M; i++) {
		cin >> p[i].x >> p[i].y;
		if (p[i].x == 1) x_min = min(x_min, p[i].y);
		if (p[i].y == 1) y_min = min(y_min, p[i].x);
	}
	// cout << M << endl;
	
	for (int i = x_min + 1; i <= W; i++) p[++M] = {1, i};
	for (int i = y_min + 1; i <= H; i++) p[++M] = {i, 1};
	
	
	sort(p + 1, p + 1 + M);
	M =  unique(p + 1, p + M + 1) - (p + 1);
	
	// for (int i = 1; i <= M; i++) cout << p[i].x << " " << p[i].y << endl;
	int tmp = 0, h = 1;
	for (int i = 1; i <= M; i++) {
		if (!vis[p[i].y]) {
			vis[p[i].y] = 1;
			add(p[i].y, W);
			// cout << "---" << endl;
		}
		
		if (i == M || p[i].x != p[i + 1].x) {
			tmp += query(W) - query(p[h].y - 1);
			h = i + 1;
		}
	}
	cout << 1ll * H * W - tmp << endl;
}

int32_t main() {
	work();
}