Codeforces Round 902 Div. 2 - A B C(规律) D(思维暴力) E(toposort)
A. Goals of Victory
对给定 n - 1 组队伍的净得分求和取负即为最后一组队伍的净得分
B. Helmets in Night Light
赛时想法假了,赛后更正
对所有人按照传递花费升序排序,从小到大逐步选取
先花费 p 为传递花费最小的居民分享消息,再一次遍历后面的居民
如果当前居民的传递花费 b 小于等于 p,则当前居民必选,统计其能分享消息给几个居民和花费,且由于 a > 1,故当前居民的被传递花费已经由前面计算过,而不是说将之前的花费花在后面的居民上
如果当前居民的传递花费大于 p,则应该直接传递花费 p 划算
详见代码
Qiansui_code
C. Joyboard
不限制 m 的范围,看所有的数字会出现多少种类
| 1 | 2 | 3 | 4 | ... | n - 1 | n | n + 1 |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 |
| 0 | 1 | 1 | 1 | ... | 1 | 1 | 1 |
| 0 | 0 | 2 | 2 | ... | 2 | 2 | 2 |
| 0 | 0 | 0 | 3 | ... | 3 | 3 | 3 |
| \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) |
| 0 | 0 | 0 | 0 | ... | 0 | n - 1 | n - 1 |
| 0 | 0 | 0 | 0 | ... | 0 | 0 | n |
| 0 | 1 | 1 | 1 | ... | 1 | 1 | n + 1 |
| 0 | 0 | 2 | 2 | ... | 2 | 2 | n + 2 |
| \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) |
| 0 | 0 | 0 | 0 | ... | 0 | 0 | 2n |
| 0 | 1 | 1 | 1 | ... | 1 | 1 | 2n + 1 |
| 0 | 0 | 2 | 2 | ... | 2 | 2 | 2n + 2 |
| \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) | \(\vdots\) |
所以,可得:
\(k = 1, a_{n + 1} = 0\)
\(k = 2, a_{n + 1} \in [1, n - 1] \cap\{ t | t = an, a \in N^+ \} 且 n > 1\)
\(k = 3, a_{n + 1} \in [bn + 1, (b + 1)n - 1],b \in N^+ 且 n > 2\)
$k > 3 $ 无解
D. Effects of Anti Pimples
注意题目的绿色涂的是下标的倍数
先预处理出每个下标被选中涂黑时其下标倍数中的最大值,再对这些最大值排序,从小到大依次选择当前下标 i 和前面 i - 1 个下标构成的集合的任意子集(子集个数为 \(2^{i - 1}\) 个),此时该集合中的最大值即为下标 i 代表的数
void solve(){
int n;
cin >> n;
vector<int> a(n + 1), mx(n + 1, 0);
for(int i = 1; i <= n; ++ i){
cin >> a[i];
}
for(int i = 1; i <= n; ++ i){
for(int j = i; j <= n; j += i){
mx[i] = max(mx[i], a[j]);
}
}
ll ans = 0, base = 1;
sort(mx.begin() + 1, mx.begin() + 1 + n);
for(int i = 1; i <= n; ++ i){
ans = (ans + base * mx[i] % mod) % mod;
base = base * 2 % mod;
}
cout << ans << '\n';
return ;
}
E. Autosynthesis
如果第 i 个下标没有被圈,那么下标 a[i] 必定被圈
如果第 i 个下标被圈了,那么下标 a[i] 可能被圈
那么我们对于每一个 i 向 a[i] 建边,表示不圈与必圈的关系,一共会有 n 个顶点,n 条边,且每个顶点最多在一个环中
如果说图中存在入度为 0 的节点 i,那么节点 i 必须不圈,那么节点 a[i] 必须被圈,那么节点 a[[i]] 的入度也需要 -1,若其入度为 0 则其成为新的入度为 0 的节点
故可以利用 toposort 来处理哪些节点必须被保留
经过这样的操作之后图中剩下的就是环了,对于环,我们可以随意找环上任意一点进行上述操作,同时标记其圈或不圈的状态,如果说存在一个节点又要圈又要不圈,那么该情况就无法满足,输出 -1,否则处理完所有的环即可
此操作等价于对于一个环,如果环的节点个数为奇数,那么必定无法实现;如果环的结点个数为偶数,那么隔一个节点取一个节点即可
详见代码
//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long
using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*
*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f, mod = 998244353;
int n, ru[maxm], vis[maxm], a[maxm];
queue<int> q;
bool f = true;
void calc(){
while(q.size()){
int t = q.front(); q.pop();
if(vis[t] == -1 || vis[a[t]] == 1){
f = false; break;
}
vis[t] = 1;
if(vis[a[t]] == -1) continue;
vis[a[t]] = -1;
-- ru[a[a[t]]];
if(ru[a[a[t]]] == 0) q.push(a[a[t]]);
}
return ;
}
void solve(){
cin >> n;
for(int i = 1; i <= n; ++ i){
cin >> a[i];
++ ru[a[i]];
}
while(f){
for(int i = 1; i <= n; ++ i)
if(ru[i] == 0 && vis[i] == 0) q.push(i);
if(q.size() == 0){
for(int i = 1; i <= n; ++ i){
if(vis[i] == 0){
q.push(i); calc();
}
}
break;
}else calc();
}
if(f){
vector<int> ans;
for(int i = 1; i <= n; ++ i)
if(vis[i] == 1) ans.push_back(a[i]);
cout << ans.size() << '\n';
for(auto x : ans) cout << x << ' ';
}else cout << -1 << '\n';
return ;
}
signed main(){
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
// cin >> _;
while(_ --){
solve();
}
return 0;
}
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/17750143.html

浙公网安备 33010602011771号