AtCoder Beginner Contest 129 解题报告

传送门

写了四个题就跑去打球了。第五题应该能肝出来的。

A - Airplane

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

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
    return x * f;
}

int main() {
    int a = read(), b = read(), c = read();
    int ans = 1e9;
    ans = min(ans, a + b);
    ans = min(b + c, ans);
    ans = min(ans, c + a);
    cout << ans << '\n';
    return 0;
}
View Code

B - Balance

看错题意了。。改的时候就直接暴力了一发。。

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

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
    return x * f;
}

const int N = 110;
int a[N], sum[N];

int main() {
    int n = read();
    for (int i = 1; i <= n; i++) a[i] = read();
    for (int i = 1; i <= n; i++) {
        sum[i] = sum[i - 1] + a[i];
    }
    int ans = 1e9;
    for (int T = 1; T < n; T++) {
        int sum0 = 0;
        for (int i = 1; i <= n; i++) {
            if (i <= T) sum0 += a[i];
            else break; 
        }
        ans = min(ans, abs(sum[n] - sum0 - sum0));
    //    printf("%d\n", ans);
    }
    printf("%d\n", ans);
    return 0;
}
View Code

C - Typical Stairs

题意:走台阶,一次走一至两个台阶,有些台阶是坏的,问走到第$n$个台阶的方案数

思路:就是普通的递推,坏的台阶$f[i]$设为0

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

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
    return x * f;
}

const int N = 1e5 + 10;
const ll mod = 1e9 + 7;
bool vis[N];
ll f[N];

int main() {
    int n = read(), m = read();
    while (m--) {
        int x = read();
        vis[x] = 1;
    }
    f[0] = 1;
    if (!vis[1]) f[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (vis[i]) continue;
        f[i] = (f[i - 1] + f[i - 2]) % mod;
    }
    printf("%lld\n", f[n]);
    return 0;
}
View Code

D - Lamp

题意:一个网格,有些地方是墙,问在哪个没有墙的地方放个灯,灯能照射的范围最远,灯能往上下左右延伸

思路:刚开始傻逼傻逼的对每个点往四个方向延伸,然后就获得了一个TLE。从左上对每个点统计从它的左方和上方分别能走多远,从右下对每个点统计从它的右方和下方分别能走多远

然后再对每一个点求一边四个方向的和的最大值

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

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
    return x * f;
}

const int N = 2020;
char s[N][N];
int dp[N][N][4];

int main() {
    int n = read(), m = read();
    for (int i = 0; i < n; i++) {
        scanf("%s", s[i]);
    }
    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (s[i][j] == '.') {
                dp[i][j][0] = dp[i][j][1] = 1;
                if (j > 0 && dp[i][j - 1][0] > 0) dp[i][j][0] = dp[i][j - 1][0] + 1;
                if (i > 0 && dp[i - 1][j][1] > 0) dp[i][j][1] = dp[i - 1][j][1] + 1;
            }
        }
    }
    for (int i = n - 1; i >= 0; i--) {
        for (int j = m - 1; j >= 0; j--) {
            if (s[i][j] == '.') {
                dp[i][j][2] = dp[i][j][3] = 1;
                if (j < m - 1 && dp[i][j + 1][2] > 0) dp[i][j][2] = dp[i][j + 1][2] + 1;
                if (i < n - 1 && dp[i + 1][j][3] > 0) dp[i][j][3] = dp[i + 1][j][3] + 1;
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (s[i][j] == '#') continue;
            int temp = 1;
            for (int cnt = 0; cnt < 4; cnt++) temp += dp[i][j][cnt];
            ans = max(ans, temp - 4);
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

E - Sum Equals Xor

题意:给一个二进制数$L$,问有多少对$\left(a,b\right)$满足:$a+b \leq L$   $a+b = a \oplus b$

思路:为啥别人看到都直接莽DP啊,为啥我看到就推公式啊。因为第二个条件,对于每一位 $a$和$b$只能为$\left(0,0\right)$ $\left(1,0\right)$ $\left(0, 1\right)$ 三种情况

所以如果给出的$L$是全1,那么答案就是$3^{len}$,但是由于第一个条件存在,那么对于每一位为0的,不能出现 1.比他高位的1的位置出现 $\left(1,0\right)$ $\left(0, 1\right)$ 2.这个位置出现$\left(1,0\right)$ $\left(0, 1\right)$ 那么就用一个系数$c$来保存1位置,每到一个1位置, $c$乘2,每到一个0位置,答案减去 $c \times 3 ^{x}$ $x$是这个位置往后的数的长度 就是前面1位置出现了一个为0一个为1 这个0位置出现一个0一个为1 $a + b$就会大于$L$ 那么后面的随机组合的情况就是多出来了 所以减去就完了。

代码里面还有一个是DP的,我是拿来对拍的...

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

const ll mod = 1e9 + 7;

ll qp(ll a, ll b) {
    ll res = 1;
    while (b) {
        if (b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}

const int N = 1e5 + 10;
char s[N];
ll dp[N];
ll bit[N];

int main() {
    scanf("%s", s);
    int len = strlen(s);
    ll ans = qp(3, len);
    bit[0] = 1;
    for (int i = 1; i <= len; i++) bit[i] = bit[i - 1] * 3 % mod;
    if (s[0] == '0') ans = (ans - 2 * qp(3, len - 1)) % mod;
    ll temp = 4;
    for (int i = 1; i < len; i++) {
        if (s[i] == '0') ans = (ans - temp * bit[len - i - 1] % mod + mod) % mod;
        else temp = temp * 2 % mod;
    }
//    dp[0] = 1;
//    reverse(s, s + len);
//    for (int i = 0; i < len; i++) {
//        if (s[i] == '1') dp[i + 1] = (2 * dp[i] + bit[i]) % mod;
//        else dp[i + 1] = dp[i];
//    }
    printf("%lld\n", ans);
    return 0;
}
View Code

F - Takahashi's Basics in Education and Learning

题意:给一个等差数列的首项和公差和项数,把这$L$项给拼起来,问最后这个大数模$M$的答案是多少

思路:完全没明白咋写...看了别人的代码看半天才懂...

这个大数的组成就是$a_{0}\times 10^{b_{0}\cdot }+a_{1}\times 10^{b_{1}}+\ldots +a_{L - 1}\times 10^{b_{L - 1}}$

答案把这$L$项按他们的长度分类 然后对于每一个构造一个矩阵

$\begin{pmatrix} bit & 1 & 0 \\ 0 & 1 & d \\ 0 & 0 & 1 \end{pmatrix}$

答案矩阵为$\begin{pmatrix} ans \\ a_{st} \\ 1 \end{pmatrix}$

找到$a_{st}$二分就OK了

学习了。

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

inline ll read() {
    ll x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
    return x * f;
}

ll mod;

struct M { ll a[3][3]; };
M operator * (const M &a, const M &b) {
    M c;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            c.a[i][j] = 0;
            for (int k = 0; k < 3; k++) {
                c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j] % mod) % mod;
            }
        }
    }
    return c;
}

M qp(M a, ll b) {
    M c;
    for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) c.a[i][j] = i == j;
    while (b) {
        if (b & 1) c = c * a;
        a = a * a;
        b >>= 1;
    }
    return c;
}

int main() {
    ll n = read(), a0 = read(), d = read(); mod = read();
    ll bit = 10, ans = 0;
    ll st = 0;
    for (int i = 1; i <= 19; i++) {
        ll l = st, r = n, p = -1;
        while (l + 1 < r) {
            ll mid = l + r >> 1;
            if (mid * d + a0 < bit) l = mid , p = mid;
            else r = mid;
        }
        if (l * d + a0 < bit) p = l;
        if (p != -1) {
            M a;
            a.a[0][0] = bit % mod; a.a[0][1] = a.a[1][1] = a.a[2][2] = 1LL;
            a.a[0][2] = a.a[1][0] = a.a[2][0] = a.a[2][1] = 0LL;
            a.a[1][2] = d % mod;
            a = qp(a, p - st + 1);
            ll ast = a0 % mod + d % mod * st % mod; ast %= mod; 
            ans = (ans * a.a[0][0] % mod + ast * a.a[0][1] % mod + a.a[0][2] % mod) % mod;
            st = p + 1;
        }
        if (st >= n) break;
        bit *= 10;
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

 

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/11001268.html
今日推荐