AtCoder Beginner Contest 132 解题报告

Posted mrzdtz220

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 (ch >= 0 && ch <= 9)  x = x * 10 + ch - 48; ch = getchar(); 
    return x * f;


const int N = 1e5 + 10;
int a[N];

int main() 
    int n = read();
    for (int i = 0; i < n; i++) a[i] = read();
    sort(a, a + n);
    printf("%d\n", a[n / 2] - a[n / 2 - 1]);
    return 0;
View Code

 

D Blue and Red Balls

技术图片
#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 (ch >= 0 && ch <= 9)  x = x * 10 + ch - 48; ch = getchar(); 
    return x * f;


const int MOD = 1e9 + 7;
const int N = 2010;
int C[N][N];

void init() 
    C[0][0] = 1;
    C[1][0] = C[1][1] = 1;
    for (int i = 2; i < N; i++) 
        C[i][0] = 1;
        for (int j = 1; j <= i; j++) 
            C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
    


int main() 
    init();
    int n = read(), k = read();
    for (int i = 1; i <= k; i++) 
        printf("%d\n", 1LL * C[k - 1][i - 1] * C[n - k + 1][i] % MOD);
    
    return 0;
View Code

 

E Hopscotch Addict

题意:给一个有向图,问能不能从$S$,走$3^x$ $x \geq 1$ 能输出$x$,不能输出-1

思路:BFS。刚开始想的是对每一个点,枚举它往后走三步的点,但是T了。正解应该用$dis\left[ i\right] \left[ k\right]$表示走到$i$,并且走的步数模3等于$k$ 然后BFS就OK了。

技术图片
#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 = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int n, m, s, t, dis[N][3];
vector<int> G[N];

void bfs() 
    memset(dis, -1, sizeof(dis));
    dis[s][0] = 0;
    queue< pair<int, int> > que;
    que.push(s, 0);
    while (!que.empty()) 
        pair<int, int> u = que.front(); que.pop();
        for (auto v : G[u.first]) 
            if (dis[v][(u.second + 1) % 3] < 0) 
                dis[v][(u.second + 1) % 3] = dis[u.first][u.second] + 1;
                que.push(v, (u.second + 1) % 3);
            
        
    


int main() 
    n = read(), m = read();
    while (m--) 
        int u = read(), v = read();
        G[u].push_back(v);
    
    s = read(), t = read();
    bfs();
    if (dis[t][0] == -1) puts("-1");
    else printf("%d\n", dis[t][0] / 3);
    return 0;
View Code

 

F Small Products

题意:给定一个$N$,$K$,问长度为$K$,且相邻两数的乘积不超过$N$的方案数。

思路:我只会$O\left( KN^2\right)$的暴力。看了题解瞬间觉得...tql

将数分为小于等于$\sqrt N$和大于$\sqrt N$,记为$s$和$b$

把$b$分成$\sqrt N$块 第$i$块表示$i\cdot b\leq N$ 那么这个块里有$\dfrac Ni-\dfrac Ni+1$个数

$S\left( i,j\right)$表示长度为$i$,最后一个数为$j$ ($j\leq \sqrt N$)的方案数

$B\left( i,j\right)$表示长度为$i$,最后一个数在块$B^j$里($j\leq \sqrt N$)的方案数

一个小的数前面可以放任意一个小的数,也可以放一个大数,这个数与这个小的数乘积小于等于$N$

那么$S$的递推式子是$S\left( i,j\right) =\sum ^\sqrt N_k=1s\left( i-1,k\right) +\sum ^\sqrt N_k=jB\left( i-1,k\right)$

$B$的递推式子是$B\left( i,j\right) =\left( \dfrac Nj-\dfrac Nj+1\right) \sum ^j_k=1S\left( i-1,k\right)$

$ans=\sum ^\sqrt N_i=1\left( S\left( k,i\right) +B\left( k,i\right) \right)$

但是这样复杂度是$O\left( k\left( \sqrt N\right) ^2\right)$

在计算的过程中计算完这一层可以把这一层的给求个和,复杂度就降为$O\left( k\sqrt N\right)$

好题。

技术图片
#include <cstdio>
#include <cstring>
#include <cmath>
#define ll long long
using namespace std;

const ll MOD = 1e9 + 7;
const int N = 5e4 + 10;
ll S[110][N], B[110][N];

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 n = read(), k = read();
    int r = sqrt(n) + 1;
    S[0][1] = 1;
    for (int i = 0; i < k; i++) 
        for (int j = 1; j < r; j++) S[i][j] = (S[i][j] + S[i][j - 1]) % MOD;
        for (int j = r - 2; j > 0; j--) B[i][j] = (B[i][j] + B[i][j + 1]) % MOD;
        for (int j = 1; j < r; j++) 
            B[i + 1][j] = S[i][j] * (n / j - n / (j + 1));
            if (j == n / j) B[i + 1][j] = 0; //已被包含在S里
            B[i + 1][j] %= MOD;
        
        for (int j = 1; j < r; j++) 
            S[i + 1][j] = B[i][j] + S[i][r - 1];
            S[i + 1][j] %= MOD;
        
    
    ll ans = 0;
    for (int i = 1; i <= r; i++) ans = (ans + B[k][i] + S[k][i]) % MOD;
    printf("%lld\n", ans);
    return 0;
View Code

 

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

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242