首页 > 其他分享 >Codeforces Round 902 (Div. 2) (CF1877) B、C、D 题解

Codeforces Round 902 (Div. 2) (CF1877) B、C、D 题解

时间:2023-10-08 23:22:08浏览次数:49  
标签:902 cnt CF1877 题解 ll int cdots using mod

B

题目大意

你要传话给 \(n\) 个人,每传一下话需要花费 \(p\) ,当一个人被传话后,他可以最多传给 \(a_i\) 个人,每次花费 \(b_i\) 。问把话传给 \(n\) 个人的最小花费。

分析

首先传给第一个人只少要 \(p\)

下来贪心,每次让花费最小、且能够传话的人去传话。

考虑建一个堆,堆内的信息是花费 \(x\) 和能传的次数 \(y\) ,堆顶是最小的花费 \(x\) ,然后进行如下的 \(n\) 次操作:

  • 取出堆顶,进行一次传话,其 \(y\) 减一
  • 若 \(y\) 变为 \(0\) ,则将其从堆中弹出

一共会进行 \(n\) 次操作,复杂度 \(O(n~log~n)\)

Code (注意开 C++ 20)

#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false); cin.tie(0)
using namespace std;
using ll = long long;
int n, p;
void solve() {
    map<ll, ll> cnt;
    cin >> n >> p;
    vector<ll> a(n + 1), b(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) {
        cin >> b[i];
        cnt[b[i]] += a[i];
    }
    cnt[p] += n;
    ll ans = p;
    for (int i = 1; i < n; i++) {
        auto [x, y] = *cnt.begin();
        ans += x;
        if (y == 1)
            cnt.erase(cnt.begin());
        else
            cnt[x]--;
    }
    cout << ans << endl;
}

int main() {
    IO;
    int T;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

C

题目大意

要求你构造一个长度为 \(n+1\) 的数组,你可以给 \(a_{n+1}\) 赋一个 \([0,m]\) 之间的值,随后 \(\forall i \in [1,n],~a_i=a_{i+1} ~mod ~i\)

问最后数组中有 \(k\) 个不同数的方案数

分析

注意到无论赋的这个值 \(a_{n+1}\) 有多大,下一个数 \(a_n\) 一定满足 \(a_n<n\) ,且 \(a_1=0\)

假设 \(a_{n+1}=x+tn\) ,那么数组的情况如下:

\(i\) \(1\) \(2\) \(\cdots\) \(x\) \(\cdots\) \(n\) \(n+1\)
\(a_i\) \(0\) \(0\) \(0\) \(0\) \(x\) \(x\) \(x+tn\)

所以数组最多存在 \(3\) 种不同的数字 ,当 \(k>3\) ,\(ans=0\)

下面分情况讨论:

  • \(k=1\) ,那么 \(a_{n+1}=x+tn\) ,\(ans=1\)

  • \(k=2\) ,有两种情况:

    • \(a_{n+1} \equiv a_n~mod~n\) ,即 \(a_{n+1}<n\) ,总共有 \(min(n-1,m)\) 种
    • \(a_{n+1} \equiv 0~mod~n\) ,那么构造出来的数组是 \(\forall i\in[1,n],~a_i=0,~a_{n+1}=x\) ,总共有 \(\lfloor \frac{n}{m}\rfloor\) 种
  • \(k=3\) ,答案是 \(m-上面的答案之和\) 种

Code

#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false); cin.tie(0)
using namespace std;

void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    if (k >= 4) {
        cout << 0 << endl;
    } else if (k == 3) {
        if (m < n) cout << 0 << endl;
        else cout << m - n - m / n + 1 << endl;
    } else if (k == 2) {
        if (m <= n) cout << m << endl;
        else cout << n + m / n - 1 << endl;
    } else {
        cout << 1 << endl;
    }
}

int main() {
    IO;
    int T;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

D

题目大意

给出 \(n\) 个点的值,选择将一些点染成黑色,只少染一个。如果染黑了点 \(i\) ,那么 \(i\) 的所有倍数的点会被染成绿色。

每次染色后,答案是被染色的点的最大值

一共有 \(2^n-1\) 种染色方式,问所有染色方式的答案之和。

分析

考虑每一个点对整个答案的贡献:

首先这个点需要是所有选中点里最大的,才会产生贡献。

换句话说,只有比这个点大的点都都已经被计算完毕,排除掉后,它才会产生贡献。

那么考虑将点的值排序,从大往小考虑:

如果当前点 \(i\) 是最大的点,比 \(i\) 大的点已经被排除在外了,还剩下 \(k\) 个点,也就是点集 \(\{i_1,i_2,\cdots,i_k\}\)

  • 假设这剩下的 \(k\) 个点中,是 \(a_i\) 的因数的点有 \(l\) 个,点集为 \(\{j_1,j_2,\cdots,j_l\}\) ,其中 \(i \in \{j_1,j_2,\cdots,j_l\}\)

    那么 \(i\) 这个点产生的贡献值为 \(a_i \times (2^{k-1}+2^{k-2}+\cdots + 2^{k-l})\)

  • 随后我们将属于 \(a_i\) 因数的点集 \(\{j_1,j_2,\cdots,j_l\}\) 从 \(\{i_1,i_2,\cdots,i_k\}\) 中删掉,继续考虑剩下的点中最大的那个数

下来考虑如何知道属于点 \(i\) 的因数有哪些?以及这些点有没有在考虑 \(i\) 之前被考虑到:

我的方法是建立一张图,如果点 \(u\) 是点 \(v\) 的倍数,那么建立一条 \(u\rightarrow v\) 边,建图的复杂度是 \(O(n\sqrt{n})\)

每次考虑点 \(i\) 就在这张图上从 \(i\) 顺着往下找。

Code

#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false); cin.tie(0)
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
const ll mod = 998244353;
const int N = 1e5 + 5;
int n, cnt;
pll a[N];
ll ans;
vector<int> G[N];
ll qpow(ll x, ll y) {
    ll res = 1;
    while (y) {
        if (y & 1) res = res * x % mod;
        y >>= 1;
        x = x * x % mod;
    }
    return res;
}
bool vis[N];
void init() {
    for (int i = 1; i * i <= n; i++) {
        for (int j = i * i; j <= n; j++) {
            if (j % i == 0) {
                G[j].push_back(i);
                if (j != i * i && i != 1)
                    G[j].push_back(j / i);
            }
        }
    }
}
void dfs(int now, ll val) {
    cnt--;
    ans += qpow(2, cnt) * val;
    ans %= mod;
    for (int son : G[now]) {
        if (vis[son]) continue;
        vis[son] = true;
        dfs(son, val);
    }
}

int main() {
    IO;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i].first;
        a[i].second = i;
    }
    sort(a + 1, a + n + 1);
    cnt = n;
    init();
    for (int i = n; i >= 1 && cnt > 0; i--) {
        if (vis[a[i].second]) continue;
        vis[a[i].second] = true;
        dfs(a[i].second, a[i].first);
    }
    cout << ans;
    return 0;
}

标签:902,cnt,CF1877,题解,ll,int,cdots,using,mod
From: https://www.cnblogs.com/tonyhgf/p/17750469.html

相关文章

  • 题解 尼克的任务
    有一种和题解区完全不同的做法。首先将所有任务按照时间从小到大排序,接着用\(f_i\)表示处理前\(i\)个任务所能得到的最大空闲时间。回顾一下需要满足的条件:再某个有任务的时刻,如果尼克是空闲的,就必须从中选择一个任务做。那么我们对于第\(i\)个任务,枚举上一个做的任务\(j......
  • P7710 [Ynoi2077] stdmxeypz 题解
    P7710[Ynoi2077]stdmxeypz题解我的第一道Ynoi题,体验感不高,调了大半天,最后发现有个地方\(B_1\)写成\(B_2\)了。分析树上问题,明显是要转到树下的,所以DFS序是一定要求的。有关树上距离,所以\(deep\)数组也是一定要求的。所以我们现在把问题转化成了:给你三个序列\(......
  • Codeforces Round 902 Div. 2 - A B C D
    目录A.GoalsofVictoryB.HelmetsinNightLightnull传送门A.GoalsofVictory对给定n-1组队伍的净得分求和取负即为最后一组队伍的净得分B.HelmetsinNightLight赛时想法假了,赛后更正对所有人按照传递花费升序排序,从小到大逐步选取先花费p为传递花费最小的居......
  • Codeforces Round #902 (Div.1)
    A注意到\(a_i\ge1\),因此我们先花\(p\)的代价买下\(b\)最小的,然后一定可以一直用当前可能的最小代价买下后续的人。不难发现这一定是最优的方案。只需要将序列排序或者用std::multiset来维护。单组数据时间复杂度\(O(n\logn)\)。https://codeforces.com/contest/1876/......
  • 「Round C10 B」间隔 题解
    简要题意本题有\(T\)组数据。给定一个由\(n\)个元素构成的正整数数列\(a_1,a_2,a_3...a_{n-1},a_n\)。问至少需要插入多少个整数才能使得\(a\)的各相邻元素之差相等(不能插入在头尾)。\(a\)数列保证是单调不减的。\(1\len\le10^6,0\lea_i\le10^6,1\leT\le1......
  • DBeaver [安装/问题解决]
     DBeaverMac版软件简介DBeaverMac版是一款专门为开发人员和数据库管理员设计的免费开源通用数据库工具。软件的易用性是它的宗旨,是经过精心设计和开发的数据库管理工具。免费、跨平台、基于开源框架和允许各种扩展写作(插件)。下载地址......
  • 【题解】CodeForces-1874/1875
    CodeForces-1875AJellyfishandUndertale一定是等待降到\(1\)或者能补满到\(a\)时才使用工具,依题意模拟即可。提交记录:Submission-CodeForcesCodeForces-1874AJellyfishandGame这种题目有点思路但是不是很会。赛时第一发写得根据奇偶性判断,\(k\)为偶数错了,然后感......
  • AtCoder Beginner Contest 323 (ABC 323) D、E、F 题解
    AtCoderBeginnerContest323(ABC323)D、E、F题解D题目大意给\(n\)种数\(s_i\),每一种数有\(c_i\)个,每次可以把两个相同的数合并为一个数,问最后会剩下多少数?分析对于每一个数\(s_i\),它最多被分解\(log_2c_i\)次,并且合并出来最大的数的大小小于\(s_i\timesc_i......
  • Hadoop问题解决(3)
    在启动hadoop过程中,出现如下错误:192.168.10.100:Invalidmaximumheapsize:-Xmx0m192.168.10.100:CouldnotcreatetheJavavirtualmachine.192.168.10.100:jobtracker已死,但pid文件仍存此时查看jobtracker的日志,1[root@ccloud100manager]#vim/var/log/hado......
  • hadoop问题解决(4)
    默认配置是将datanode,namenode,jobtracker,tasktracker,secondarynamenode的pid存放在/tmp目录下,随着linux的定期清理,这些pid就不见了,当然就无法停止了,怎么解决呢?在/tmp目录创建或者修改hadoop-hadoop用户名-datanode.pid 里面写入对应的pid, 可通过jps查看. namen......