AtCoder Beginner Contest 186 A~F


传送门: https://atcoder.jp/contests/abc186/tasks


A - Brick 签到

#include <bits/stdc++.h>

using namespace std;

void solve() {
    int n, m; cin >> n >> m;
    cout << n / m << endl;
}

signed main() {
    solve();
}



B - Blocks on Grid 暴力

先 找 矩 阵 最 小 值 m x , 最 后 找 a n s = m p [ i ] [ j ] − m x 先找矩阵最小值mx,最后找ans=mp[i][j] - mx mx,ans=mp[i][j]mx

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int mp[105][105];

void solve() {
    int mx = 99999999;
    int n, m; cin >> n >> m;
    for(int i = 1;i <= n; i++) {
        for(int j = 1;j <= m; j++) {
            cin >> mp[i][j];
            mx = min(mx, mp[i][j]);
        }
    }
    ll ans = 0;
    for(int i = 1;i <= n; i++) {
        for(int j = 1;j <= m; j++) {
            ans += mp[i][j] - mx;
        }
    }
    cout << ans << endl;
}

signed main() {
    solve();
}



C - Unlucky 7 暴力

分 别 找 十 进 制 下 和 八 进 制 中 不 出 现 7 这 个 数 的 个 数 。 分别找十进制下和八进制中不出现7这个数的个数。 7

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

void solve() {
    int n; cin >> n;
    ll ans = n;
    for(int i = 7;i <= n; i++) {
        int tt = i;
        bool flag1 = 0;
        while(tt) {
            if(tt % 10 == 7) {
                flag1 = 1;
                break;
            }
            tt /= 10;
        }
        tt = i;
        bool flag2 = 0;
        while(tt) {
            if(tt % 8 == 7) {
                flag2 = 1;
                break;
            }
            tt /= 8;
        }
        if(flag1 || flag2) ans--;
    }
    cout << ans << endl;
}

signed main() {
    solve();
}



D - Sum of difference 思维

先 排 序 , 在 对 每 个 数 ∣ a j − a i ∣ 取 贡 献 。 先排序,在对每个数|a_j-a_i|取贡献。 ajai

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

void solve() {
    int n; cin >> n;
    vector<ll> v(n + 1), sum(n + 1);
    v[0] = -1e9;
    for(int i = 1;i <= n; i++) cin >> v[i];
    sort(v.begin(), v.end());
    ll ans = 0;
    for(int i = 1;i <= n; i++) {
        sum[i] = sum[i - 1] + v[i];
    }
    for(int i = 1;i <= n - 1; i++) {
        ans += (sum[n] - sum[i]) - (n - i) * v[i];
    }
    cout << ans << endl;
}

signed main() {
    solve();
}



E - Throne 扩展欧几里得

求 K x + N y = N − S 的 最 小 正 整 数 x , 有 则 输 出 , 无 则 输 出 − 1 。 求Kx+Ny=N-S的最小正整数x,有则输出,无则输出-1。 Kx+Ny=NSx1

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll ex_gcd(ll a, ll b, ll &x, ll &y)
{
    ll res, t;
    if(!b)
    {
        x = 1;
        y = 0;
        return a;
    }
    res = ex_gcd(b, a % b, x, y);
    t = x;
    x = y;
    y = t - (a / b) * y;
    return res;
}

ll solve_ex_gcd(ll a, ll b, ll c, ll &x, ll &y)
{
    ll d = ex_gcd(a, b, x, y);
    if(c % d)
    {
        x = -1;
        y = -1;
        return -1;
    }
    x *= (c / d);
    b = abs(b / d);
    x %= b;
    while(x < 0) {
        x += b;
    }
    y = (c - a * x) / b;
    return 0;
}

void solve() {
    int _; cin >> _;
    while(_--) {
        ll x, y;
        ll N, S, K; cin >> N >> S >> K;
        solve_ex_gcd(K, N, N - S, x, y);
        cout << x << endl;
    }
}

signed main() {
    solve();
}



F - Rook on Grid 扫描线 + BIT

我们到达一个点,有两种走法,先右在下和先下在右
但是对于x=1或y=1的情况,有一个障碍堵在中间,那么也是走不到的,所以我们先找最小的x=1是的y和最小的y=1时的x,在把这两个障碍之后的所有格子都设为障碍。
然后记得去重(可能重复添加障碍)。

int upx = H + 1, upy = W + 1;
    for(int i = 1;i <= M; i++) {
        cin >> p[i].x >> p[i].y;
        if(p[i].x == 1) upy = min(upy, p[i].y);
        if(p[i].y == 1) upx = min(upx, p[i].x);
    }
    for(int i = upx + 1;i <= H; i++) {
        p[++M].x = i; p[M].y = 1;
    }
    for(int j = upy + 1;j <= W; j++) {
        p[++M].y = j; p[M].x = 1;
    }

我们怎么找那些去不到的格子呢?
答:我们利用扫描线的思想,先纵向扫描,在横向搜索,在做ans贡献。

如果一个格子既不能右下走也不能下右走,那么这个格子到达不了。
纵向扫描:
用BIT维护右下路径被堵住的列,将这些格子视为到达不了。

横向搜索:
对于每一行,计算区间和,因为右下到不了,但是下右可能到达,所以我们将这些重新加回来。

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
#define lowbit(x) x & (-x)

const int N = 1e6 + 10;
ll t[N];

void modify(int x, int n) {
    while(x <= n) {
        t[x]++;
        x += lowbit(x);
    }
}

ll query(int x) {
    ll ans = 0;
    while(x) {
        ans += t[x];
        x -= lowbit(x);
    }
    return ans;
}

struct Point {
    int x, y;
    friend bool operator < (const Point &a,const Point &b){
        return a.x == b.x ? a.y < b.y : a.x < b.x;
    }
    friend bool operator == (const Point &a,const Point &b){
        return a.x == b.x && a.y == b.y;
    }
}p[N];

bool vis[N];

void solve() {
    int H, W, M;
    cin >> H >> W >> M;
    int upx = H + 1, upy = W + 1;
    for(int i = 1;i <= M; i++) {
        cin >> p[i].x >> p[i].y;
        if(p[i].x == 1) upy = min(upy, p[i].y);
        if(p[i].y == 1) upx = min(upx, p[i].x);
    }
    for(int i = upx + 1;i <= H; i++) {
        p[++M].x = i; p[M].y = 1;
    }
    for(int j = upy + 1;j <= W; j++) {
        p[++M].y = j; p[M].x = 1;
    }
    sort(p + 1, p + M + 1);
    M = unique(p + 1, p + M + 1) - (p + 1);

    int h = 1;
    ll ans = 0;
    for(int i = 1;i <= M; i++) {
        // 纵向扫描
        if(vis[p[i].y] == 0) {
            vis[p[i].y] = 1;
            modify(p[i].y, W);
        }

        // 横向扫描
        if(i == M || p[i + 1].x != p[i].x) {
            ans += query(W) - query(p[h].y - 1);
            h = i + 1;
        }
    }
    cout << (1ll * H * W - ans) << endl;
}

signed main() {
    solve();
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值