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;
}

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;
}

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;
}

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;
}

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;
}

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;
}

原文地址:https://www.cnblogs.com/Mrzdtz220/p/11001268.html

时间: 2024-11-08 08:32:09

AtCoder Beginner Contest 129 解题报告的相关文章

AtCoder Beginner Contest 117 解题报告

果然abc都是手速场. 倒序开的qwq. D题因为忘记1e12二进制几位上界爆了一发. A - Entrance Examination 就是除一下就行了... 看样例猜题意系列. #include<cstdio> #include<algorithm> #include<cstring> int main(){ double t,x; scanf("%lf%lf",&t,&x); printf("%lf",t/x

AtCoder Beginner Contest 120 解题报告

为啥最近都没有arc啊... A - Favorite Sound #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <queue> #include <cmath> #include <stack> #

Atcoder Beginner Contest 124 解题报告

心态爆炸.本来能全做出来的.但是由于双开了Comet oj一个比赛,写了ABC就去搞那个的B题 还被搞死了. 回来写了一会D就过了.可惜比赛已经结束了.真的是作死. A - Buttons #include <cstdio> using namespace std; int main() { int x, y; scanf("%d%d", &x, &y); int ans = x > y ? x : y; if (x > y) x--; else

AtCoder Beginner Contest 125 解题报告

那天晚上刚好有事就咕了. 最近的那一场E题还不会写.F题全场又只过了三个?留坑吧... A - Biscuit Generator #include <cstdio> 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 (

AtCoder Beginner Contest 132 解题报告

前四题都好水.后面两道题好难. C Divide the Problems #include <cstdio> #include <algorithm> 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 (c

【AtCoder】AtCoder Grand Contest 040 解题报告

点此进入比赛 \(A\):><(点此看题面) 大致题意: 给你一个长度为\(n-1\).由\(<\)和\(>\)组成的的字符串,第\(i\)位的字符表示第\(i\)个数和第\(i+1\)个数的大小关系,求这个由非负整数组成的数组中元素和的最小值. 送分题都想了几分钟才做出来,真是退役预警...... 显然,对于所有小于两旁的数,我们给它赋值为\(0\),然后再从它们向两边扩展即可. #include<bits/stdc++.h> #define Tp template&

AtCoder Beginner Contest 103 D(贪心)

AtCoder Beginner Contest 103 D 题目大意:n个点,除第n个点外第i与第i+1个点有一条边,给定m个a[i],b[i],求最少去掉几条边能使所有a[i],b[i]不相连. 按右端点从小到大排序,如果当前选的去掉的边在区间内,那么符合条件,否则ans++,并贪心地把去掉的边指向右端点,因为前面的区间都满足条件了,所以要去掉的边要尽量向右移使其满足更多的区间. 1 #include <iostream> 2 #include <cstdio> 3 #incl

AtCoder Beginner Contest 136

AtCoder Beginner Contest 136 Contest Duration : 2019-08-04(Sun) 20:00 ~ 2019-08-04(Sun) 21:40 Website: AtCoder BC-136 后面几题都挺考思考角度D. C - Build Stairs 题目描述: 有n座山从左到右排列,给定每一座山的高度\(Hi\),现在你可以对每座山进行如下操作至多一次:将这座山的高度降低1. 问是否有可能通过对一些山进行如上操作,使得最后从左至右,山的高度呈不下降

AtCoder Beginner Contest 154 题解

人生第一场 AtCoder,纪念一下 话说年后的 AtCoder 比赛怎么这么少啊(大雾 AtCoder Beginner Contest 154 题解 A - Remaining Balls We have A balls with the string S written on each of them and B balls with the string T written on each of them. From these balls, Takahashi chooses one