AtCoder Beginner Contest 129 解题报告

Posted mrzdtz220

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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$项按他们的长度分类 然后对于每一个构造一个矩阵

$\beginpmatrix bit & 1 & 0 \\ 0 & 1 & d \\ 0 & 0 & 1 \endpmatrix$

答案矩阵为$\beginpmatrix ans \\ a_st \\ 1 \endpmatrix$

找到$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

 

 

以上是关于AtCoder Beginner Contest 129 解题报告的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242