AtCoder Beginner Contest 164

传送门

A - Sheep and Wolves

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    int a, b;
    scanf("%d%d", &a, &b);
    printf("%s
", a <= b ? "unsafe" : "safe");
    return 0;
}
A.cpp

B - Battle

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    int a, b, c, d;
    scanf("%d%d%d%d", &a, &b, &c, &d);
    printf("%s
", (c + b - 1) / b <= (a + d - 1) / d ? "Yes" : "No");
    return 0;
}
B.cpp

C - gacha

题意:给N个字符串S,求有多少个不同的字符串。

数据范围:$ 1 leq N leq 2 imes 10^{5} , 1 leq |S| leq 10$

题解:放set里计数即可。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
unordered_set<string> S;
int main() {
    int n;
    cin >> n;
    for(int i = 0; i < n; i++) {
        string s;
        cin >> s;
        S.insert(s);
    }
    cout << S.size() << '
';
    return 0;
}
C.cpp

D - Multiple of 2019

题意:给一个字符串S,求有多少个子串在十进制下对2019取模为0。

数据范围:$ 1 leq |S| leq2 imes 10^{5} $

题解:跟AtCoder Beginner Contest 158 E 差不多。

可以得知$10^{x} mod 2019 eq 0$,那么对于$S[l...r]$子串,当且仅当$S[l...N] equiv S[r...N] (mod 2019)$成立时,满足要求。

证明:$S[l...r] imes 10^{r-l} = S[l...N]-S[r...N] $,若$S[l...N]-S[r...N] equiv 0(mod 2019)$,由于$10^{x} mod 2019 eq 0$,可以得出$S[l...r] mod 2019 =0$,若 $S[l...r]   equiv 0(mod 2019)$,显然$S[l...r] imes 10^{r-l} mod 2019 = 0$

倒着遍历字符串,每次加上之前余数和当前余数相同的个数。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 5;
char s[N];
int ma[2020];
int main() {
    scanf("%s", s);
    ll ans = 0;
    int res = 0, t = 1, n = strlen(s);
    for(int i = n - 1; i >= 0; i--) {
        ma[res]++;
        res = (res + (s[i] - '0') * t) % 2019;
        ans += ma[res];
        t = t * 10 % 2019;
    }
    printf("%lld
", ans);
    return 0;
}
D.cpp

 E - Two Currencies

题意:给N个城市,M条路,S个银币,每条路需要花费Ai个银币和Bi分钟,可以在第i个城市花费Di分钟获得Ci银币(无限次),求从1到2...n最少花费的时间。

数据范围:$ 2 leq N leq 50, N-1 leq M leq 100, 0 leq S leq 10^{9}, 1 leq A_{i} leq 50, 1 leq B_{i},C_{i},D_{i} leq 10^{9}$

题解:最短路,f[i][j]代表到第i个城市身上有j个银币的最少花费时间,由于A最大为50,那么身上只要有50*N的银币就可以到任意点。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 55;
struct P{
    int v, a, b;
};
vector<P> G[N];
int c[N], d[N];
ll f[N][N * N];
int main() {
    int n, m, s;
    scanf("%d%d%d", &n, &m, &s), s = min(s, 2500);
    for(int i = 0, u, v, a, b; i < m; i++) {
        scanf("%d%d%d%d", &u, &v, &a, &b);
        G[u].push_back({v, a, b});
        G[v].push_back({u, a, b});
    }
    for(int i = 1; i <= n; i++) {
        scanf("%d%d", &c[i], &d[i]);
    }
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N * N; j++) {
            f[i][j] = 1e18;
        }
    }
    f[1][s] = 0;
    typedef tuple<ll, int, int> T;
    priority_queue<T, vector<T>, greater<T>> qu;
    qu.push(T(0, 1, s));
    while(!qu.empty()) {
        ll t = get<0>(qu.top());
        int u = get<1>(qu.top()), w = get<2>(qu.top());
        qu.pop();
        if(f[u][w] > t) continue;
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].v, a = G[u][i].a, b = G[u][i].b;
            if(w >= a && f[v][w - a] > t + b) {
                f[v][w - a] = t + b;
                qu.push(T(t + b, v, w - a));
            }
        }
        if(f[u][min(w + c[u], 2500)] > t + d[u]) {
            f[u][min(w + c[u], 2500)] = t + d[u];
            qu.push(T(t + d[u], u, min(w + c[u], 2500)));
        }
    }
    for(int i = 2; i <= n; i++) {
        ll ans = 1e18;
        for(int j = 0; j <= 2500; j++) {
            ans = min(ans, f[i][j]);
        }
        printf("%lld
", ans);
    }
    return 0;
}
E.cpp

F - I hate Matrix Construction

题意:构造一个N*N的矩阵,满足如果Si为0,第i行所有元素与运算后的值为Ui,反之,第i行所有元素或运算后的值为Ui。如果Ti为0,第i列所有元素与运算后的值为Vi,反之,第i列所有元素或运算后的值为Vi

数据范围:$ 1 leq N leq 500, 0 leq S_{i},T_{i} leq 1, 0 leq U_{i},V_{i} < 2^{64}$

题解:独立考虑每一个二进制位,把问题转化成构造64个N*N的01矩阵。

如果一行(一列)与运算以后为1,那么这一行(一列)全为1,如果一行(一列)或运算以后为0,那么这一行(一列)全为0。

对于每个没确定的元素,如果该元素的对应行列需要的值相同,就把该元素赋为这个值,反之就先赋为0。

剩下的就是一行(一列)或运算以后为1的情况,可以将每行每列的01个数计数,然后遍历判断当前位置能否将0变成1即可。

最后在整体判断一下是否满足要求。

#include <bits/stdc++.h>
#define ll unsigned long long
using namespace std;
const int N = 505;
int S[N], T[N], n;
ll U[N], V[N], ans[N][N];
int t[N][N], R[N][2], C[N][2];
bool solve() {
    for(int k = 0; k < 64; k++) {
        memset(t, -1, sizeof t);
        memset(R, 0, sizeof R);
        memset(C, 0, sizeof C);
        for(int i = 1; i <= n; i++) {
            int x = (U[i] & 1);
            if(S[i] == x) continue;
            for(int j = 1; j <= n; j++) {
                if(~t[i][j] && t[i][j] != x) return false;
                t[i][j] = x;
            }
        }
        for(int i = 1; i <= n; i++) {
            int x = (V[i] & 1);
            if(T[i] == x) continue;
            for(int j = 1; j <= n; j++) {
                if(~t[j][i] && t[j][i] != x) return false;
                t[j][i] = x;
            }
        }
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                if((U[i] & 1) == (V[j] & 1)) t[i][j] = (U[i] & 1);
                if(t[i][j] == -1) t[i][j] = 0;
                R[i][t[i][j]]++;
                C[j][t[i][j]]++;
            }
        }
        for(int i = 1; i <= n; i++) {
            if(S[i] && (U[i] & 1)) {
                if(R[i][1]) continue;
                for(int j = 1; j <= n; j++) {
                    if(!T[j] && !(V[j] & 1) && C[j][0] > 1) {
                        t[i][j] = 1;
                        R[i][0]--, C[j][0]--;
                        R[i][1]++, C[j][1]++;
                        break;
                    }
                }
            }
        }
        for(int i = 1; i <= n; i++) {
            if(T[i] && (V[i] & 1)) {
                if(C[i][1]) continue;
                for(int j = 1; j <= n; j++) {
                    if(!S[j] && !(U[j] & 1) && R[j][0] > 1) {
                        t[j][i] = 1;
                        R[j][0]--, C[i][0]--;
                        R[j][1]++, C[i][1]++;
                        break;
                    }
                }
            }
        }
        for(int i = 1; i <= n; i++) {
            if(S[i] == 0 && (U[i] & 1) == 1 && R[i][1] != n) return false;
            if(S[i] == 0 && (U[i] & 1) == 0 && R[i][1] == n) return false;
            if(S[i] == 1 && (U[i] & 1) == 1 && R[i][1] == 0) return false;
            if(S[i] == 1 && (U[i] & 1) == 0 && R[i][1] != 0) return false;
            if(T[i] == 0 && (V[i] & 1) == 1 && C[i][1] != n) return false;
            if(T[i] == 0 && (V[i] & 1) == 0 && C[i][1] == n) return false;
            if(T[i] == 1 && (V[i] & 1) == 1 && C[i][1] == 0) return false;
            if(T[i] == 1 && (V[i] & 1) == 0 && C[i][1] != 0) return false;
        }
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                if(t[i][j]) ans[i][j] |= (1ull << k);
            }
        }
        for(int i = 1; i <= n; i++) {
            U[i] >>= 1;
            V[i] >>= 1;
        }
    }
    return true;
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &S[i]);
    for(int i = 1; i <= n; i++) scanf("%d", &T[i]);
    for(int i = 1; i <= n; i++) scanf("%llu", &U[i]);
    for(int i = 1; i <= n; i++) scanf("%llu", &V[i]);
    if(!solve()) printf("-1
");
    else {
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                printf("%llu%c", ans[i][j], j == n ? '
' : ' ');
            }
        }
    }
    return 0;
}
F.cpp
原文地址:https://www.cnblogs.com/zdragon1104/p/12782812.html