AtCoder Beginner Contest 231 A~F 题解

上分难,上分难,上分路,今安在/ll

还好 E 题最后 5min 完成绝杀避免掉分。

一共 10 发罚时,菜的真实。

A - Water Pressure

输出 \(\frac{x}{100}\) 即可。

B - Election

用 map 统计每个字符串的出现次数,然后暴力判断一下哪个字符串出现次数最多

C - Counting 2

给你 \(n\) 个数, \(q\) 次询问,每次询问给定一个 \(x\) ,回答有多少个数 \(\ge x\)

\(1 \le n,q \le 2 \times 10^5\)

从小到大排完序,对于每次询问,每次 lower_bound 一下第一个 \(\ge x\) 的位置 \(k\) ,这次询问答案为 \(n-k+1\)

时间复杂度 \(\mathcal O((n+q)\log n)\)

D - Neighbors

给你 \(n\) 个点,要求将他们排成一个序列,但要求满足 \(m\) 个关系。

对于每个关系 \((u,v)\) 表示 \(u\) 要和 \(v\) 相邻。最后输出能否在满足所有关系的情况下排成一个序列。

首先对于每个点要满足度数 \(\le 2\),还有一种情况是关系构成一个环也是不合法的。

判环可以直接用 dfs 或者 tarjan

E - Minimal payments

从前有一个国家,这个国家里有 \(n\) 种货币,第 \(1\) 种货币的面值为 \(a_i\)

在这里,\(1 = a_1 < a_2 < ... < a_{n-1} < a_n\) ,并且对于每个 \(i \in [1,n)\) ,都满足 \(a_{i+1}\)\(a_i\) 的倍数。

现在你要支付 \(X\) 元,你要求出一种方案,使得支付的钱的张数和找回的钱的张数的和最少。

你只需要输出这个和最小是多少。

\(1 \le n \le 60\)\(1 = a_1 < ... < a_n \le 10^{18}\)\(1 \le X \le 10^{18}\)

注意,对于每个 \(i \in [1,n)\) ,都满足 \(a_{i+1}\)\(a_i\) 的倍数。

\(n\) 的数据范围很小,考虑 dfs ,因为后面一个数是前面一个数的倍数,我们考虑从前向后 dfs 或者从后往前 dfs

先说官方题解的做法

可以发现,所有可能出现的数值为 \(\lfloor \frac{X}{a_i} \rfloor\)\(\lceil \frac{X}{a_i} \rceil\)。加上记忆化,总体复杂度为 \(\mathcal O(n)\)

具体方向是从后向前枚举使用那种货币,你可以考虑将现在的 \(X\) 补成 \(Y \equiv 0 \pmod {a_i}\) 的情况,这样你需要补的金额是 \(Y-X\),你也可以考虑把能用 \(a_i\) 支付的部分全部用 \(a_i\) 支付,最后剩下 \(X \% a_i\) 的金额需要支付。

在说一下我的卡常做法

你也可以从后向前搜,在使用了第 \(i\) 种货币后要保证 剩下的金额 $ % a_{i+1} = 0$ ,这样的复杂度是 \(\mathcal O(2^{60})\)

然后我们加一点剪枝:

  • 如果当前的答案已经超过了现有的最优的答案,直接返回。
  • 如果 (double)clock()/CLOCKS_PER_SEC >= 1.98 ,直接输出现有的答案退出程序。

只加第一个会 T 三个点,加了第二个之后就可以卡过去了。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 1e18 + 10;

int n, X, ans = INF;
int a[100];

void dfs(int pos, int sum, int cnt) {
    if((double)clock()/CLOCKS_PER_SEC >= 1.98) cout << ans << "\n", exit(0);
    if(cnt >= ans) return ;
    if(pos == n) {
        cnt = cnt + sum / a[n];
        ans = min(ans, cnt);
        return ;
    }
    int x = sum % a[pos + 1];
    if(!x) dfs(pos + 1, sum, cnt);
    else {
        dfs(pos + 1, sum - x, cnt + x / a[pos]);
        dfs(pos + 1, sum + a[pos + 1] - x, cnt + (a[pos + 1] - x) / a[pos]);
    }
}

signed main() {
    cin >> n >> X;
    for(int i = 1; i <= n; ++i) cin >> a[i];
    dfs(1, X, 0);
    cout << ans << "\n";
    return 0;
}

F - Jealous Two

给你 \(n\) 个物品,每个物品有两个属性 \(a_i, b_i\),求下面这个式子的值:

\[\sum_{i=1}^{n} \sum_{j=1}^{n} [a_i \ge a_j \&\& b_i \le b_j] \]

\(1 \le n \le 2 \times 10^5, 0 \le a_i, b_i \le 10^9\)

一个经典的二位偏序问题。

首先对 \(b\) 数组排序,消除第二个限制。

然后就变成了求 \(a\) 数组的类似逆序对的问题。

\(a\) 数组离散化后上树状数组即可。

有两点要注意:

  • \(i=j\) 时方案合法,所以最后的答案要 \(+ n\) ,(先修改在求和的写法应该不需要)
  • 当两个物品的两个值都相同是,不仅 \((i,j)\) 有贡献 \((j,i)\) 也有贡献,在外面单独统计一下即可。

时间复杂度 \(\mathcal O(n \log n)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 2e5 + 10;

struct node {
    int x, y;
    bool operator < (const node &b) const { return y == b.y ? x > b.x : y < b.y; }
}a[MAXN];

int n, Cnt = 0, ans = 0;
int date[MAXN];

namespace Bit {
    int sum[MAXN];
    int lb(int x) { return x & -x; }
    void Modify(int x, int k) { for(; x <= Cnt; x += lb(x)) sum[x] += k; }
    int Query(int x) { int res = 0; for(; x; x -= lb(x)) res = res + sum[x]; return res; }
}

signed main() {
    cin >> n;
    for(int i = 1; i <= n; ++i) cin >> a[i].x, date[i] = a[i].x;
    for(int i = 1; i <= n; ++i) cin >> a[i].y;
    sort(a + 1, a + n + 1);
    int cnt = 1;
    for(int i = 1; i <= n; ++i) {
        if(a[i].x != a[i + 1].x || a[i].y != a[i + 1].y)          
            ans = ans + (cnt * cnt - cnt) / 2, cnt = 1;
        else cnt ++;
    }
    sort(date + 1, date + n + 1), date[0] = -1000;
    for(int i = 1; i <= n; ++i) if(date[i] != date[i - 1]) date[++Cnt] = date[i];
    for(int i = 1; i <= n; ++i) a[i].x = lower_bound(date + 1, date + Cnt + 1, a[i].x) - date;
    for(int i = 1; i <= n; ++i) {
        int cnt = Bit::Query(Cnt) - Bit::Query(a[i].x - 1);
        Bit::Modify(a[i].x, 1);
        ans = ans + cnt; 
    }
    printf("%lld\n", ans + n);
    return 0;   
}

G - Balls in Boxes

[G - Balls in Boxes] [题解]

切队说他是 GF (生成函数?)板子,反正我不会生成函数,题解也没看懂。

H - Minimum Coloring

[H - Minimum Coloring] [题解]

貌似是网络流最大匹配之类的?

posted @ 2021-12-12 09:04  Suzt_ilymtics  阅读(386)  评论(0编辑  收藏  举报