(6/6) AtCoder Beginner Contest 186

(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();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值