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

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

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

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 {N}{i}-\dfrac {N}{i+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=1}s\left( i-1,k\right) +\sum ^{\sqrt {N}}_{k=j}B\left( i-1,k\right)$

$B$的递推式子是$B\left( i,j\right) =\left( \dfrac {N}{j}-\dfrac {N}{j+1}\right) \sum ^{j}_{k=1}S\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;
}

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

时间: 2024-08-30 12:48:40

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

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 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' &

AtCoder Beginner Contest 132 F - Small Products

数 sqrt 缩小范围 整除分块 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 1

AtCoder Beginner Contest 132 E - Hopscotch Addict

bfs 位置+状态 just need to calculate min value(only it is useful), so O(1*x) 挺有趣的一道题... 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include

【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