"蔚来杯"2022牛客暑期多校训练营6 题解
A. Array#
发现 ,考虑只保留 中二进制的最高位,并设其为 ,此时满足 。
考虑将问题转化为每 个数一定要有一个 。可设 ,则将其设为答案长度,按照下列算法所得的答案一定合法。
算法:
① 对 从小到大排序。
② 对于每个 ,我们考虑找第一个空位置(设其为 )填充进去,并将 一直填充下去,直到 。
这边可以保证被填充的位置一定为空,证明如下:
对于 ,有 。设被填充的位置 不为空,有 ,则 。
由于 ,从而有 。
那么 应该被填充,与原算法流程不符。
③ 对于剩下的空位置,随便填充一个1到n的数字即可。
#include<bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
const int MAXN = 1e6 + 5;
const int MOD = 998244353;
int n, m, pos, ans[MAXN];
pii a[MAXN];
signed main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i].fi);
int x;
while(a[i].fi) {
x = ( a[i].fi & (-a[i].fi) );
a[i].fi -= x;
}
a[i].fi = x, a[i].se = i;
}
sort(a + 1, a + 1 + n);
m = a[n].fi, pos = 1;
for(int i = 1; i <= n; i++) {
while(ans[pos]) pos++;
for(int j = pos; j <= m; j += a[i].fi) ans[j] = a[i].se;
}
for(int i = 1; i <= m; i++) if(!ans[i]) ans[i] = 1;
printf("%d\n", m);
for(int i = 1; i <= m; i++) printf("%d ", ans[i]);
return 0;
}
B. Eezie and Pie#
由于题目规定每个节点只能往上走不能往下走,我们可以预处理出所有点的深度并和 取最小值 ,那节点 最远可以送到 级父亲,用倍增预处理祖先,树上差分将这条链上的每一个节点答案+1即可。
#include<bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
const int MAXN = 2e6 + 5;
int n, dep[MAXN], fa[MAXN][30], val[MAXN], d[MAXN];
vector<int> G[MAXN];
void DFS(int u, int f) {
fa[u][0] = f;
for(int i = 1; i <= 25; i++) fa[u][i] = fa[ fa[u][i - 1] ][i - 1];
dep[u] = dep[f] + 1;
for(auto v : G[u]) {
if(v == f) continue;
DFS(v, u);
}
}
int LCA(int u, int v) {
if(dep[u] > dep[v]) swap(u, v);
for(int i = 25; i >= 0; i--) {
if((1 << i) & (dep[v] - dep[u])) v = fa[v][i];
}
for(int i = 25; i >= 0; i--) {
if(fa[u][i] != fa[v][i]) {
u = fa[u][i], v = fa[v][i];
}
}
return u == v ? u : fa[u][0];
}
int Find(int u, int d) {
for(int i = 0; i <= 25; i++) if(d & (1 << i)) u = fa[u][i];
if(!u) u = 1;
return u;
}
void Add(int u, int v, int k) {
val[u] += k, val[ fa[v][0] ] -= k;
}
void DFS2(int u, int f) {
for(auto v : G[u]) {
if(v == f) continue;
DFS2(v, u);
val[u] += val[v];
}
}
signed main()
{
scanf("%d", &n);
for(int i = 1; i < n; i++) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i = 1; i <= n; i++) scanf("%d", &d[i]);
DFS(1, 0);
for(int i = 1; i <= n; i++) Add(i, Find(i, min(dep[i], d[i]) ), 1);
DFS2(1, 0);
for(int i = 1; i <= n; i++) printf("%d ", val[i]);
return 0;
}
C. Forest#
考虑单独计算每条边对答案的贡献,先对所有边按权值从小到大排序。
考虑对于一条边 ,有多少生成子图满足其最小生成森林中有这条边。
可知当且仅当选择一些权值小于当前边的边加入生成子图,使得 连通时,最小生成森林不存在 。
设 表示使用前 条边,存在一个点集为 的连通块的生成子图数量; 表示点集为 的生成子图数量。 为全集。
则对于最小生成森林不存在编号为 的边 的情况,有:
考虑如何计算 。
对于 ,我们枚举所有集合 ,对于满足 的集合有 ,其余集合有 。
对于 ,我们枚举所有集合 ,对于满足 的集合有 。其中 为 的子集,且满足 或 。
其余集合有 。
暴力枚举子集求解 ,设 中有 个 1,则需要枚举 个子集,对于有 个状态的集合 ,有 个集合满足集合中有 个 1。
单次枚举子集求解 的时间复杂度
总时间复杂度
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
const int MOD = 998244353;
int n, sze, ans, a[25][25], pow2[105], f[105][(1 << 16) + 5], g[105][(1 << 16) + 5];
vector<pii> vec;
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n;
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) cin >> a[i][j];
}
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
if(a[i][j]) vec.push_back({a[i][j], i * n + j});
}
}
sort(vec.begin(), vec.end());
sze = vec.size(), ans = 0;
pow2[0] = 1;
for(int i = 1; i <= sze; i++) pow2[i] = pow2[i - 1] * 2 % MOD;
for(int i = 0; i < n; i++) f[0][1 << i] = 1;
for(int s = 0; s < (1 << n); s++) g[0][s] = 1;
for(int i = 0; i < sze; i++) {
int cnt = pow2[i];
int u = vec[i].se / n, v = vec[i].se % n, w = vec[i].fi;
for(int s = 0; s < (1 << n); s++) {
if( !(s & (1 << u) ) ) continue;
if( !(s & (1 << v) ) ) continue;
cnt -= f[i][s] * g[i][((1 << n) - 1) - s] % MOD;
cnt += MOD, cnt %= MOD;
}
ans += w * cnt % MOD * pow2[sze - 1 - i] % MOD;
ans %= MOD;
for(int s = 0; s < (1 << n); s++) {
f[i + 1][s] = f[i][s];
g[i + 1][s] = g[i][s];
if( !(s & (1 << u) ) ) continue;
if( !(s & (1 << v) ) ) continue;
f[i + 1][s] = f[i][s] * 2 % MOD;
g[i + 1][s] = g[i][s] * 2 % MOD;
for(int t = (s - 1) & s; t > s - t; t = (t - 1) & s) {
if( ( (t >> u) & 1 ) ^ ( (t >> v) & 1 ) ) {
f[i + 1][s] += f[i][t] * f[i][s - t] % MOD;
f[i + 1][s] %= MOD;
}
}
}
}
cout << ans << "\n";
return 0;
}
G. Icon Design#
对着题意直接模拟即可。
#include<bits/stdc++.h>
#define PIII pair< pair<int, int>, int >
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
int n;
char ch[1005][1005];
void Print() {
for(int i = 1; i <= 4 * n + 5; i++) {
for(int j = 1; j <= 13 * n + 19; j++) printf("%c", ch[i][j]);
printf("\n");
}
}
signed main()
{
scanf("%d", &n);
for(int j = 1; j <= 13 * n + 19; j++) ch[1][j] = ch[ 4 * n + 5 ][j] = '*';
for(int i = 2; i < 4 * n + 5; i++) {
ch[i][1] = ch[i][13 * n + 19] = '*';
for(int j = 2; j < 13 * n + 19; j++) ch[i][j] = '.';
}
for(int j = n + 2; j <= 4 * n + 6 - (n + 2); j++) {
vector<int> vec;
vec.push_back(1 + n + 1 + 1);
vec.push_back(1 + n + 1 + 2 * n + 3);
vec.push_back(1 + n + 1 + 2 * n + 3 + n + 1 + 1);
vec.push_back(1 + n + 1 + 2 * n + 3 + n + 1 + 2 * n + 3 + n + 1 + 1);
for(auto i : vec) ch[j][i] = '@';
}
//Print();
// N
pii s = {1 + n + 1, 1 + n + 1 + 1};
for(int i = 1 + n + 1 + 1; i <= 1 + n + 1 + 2 * n + 3; i++) ch[s.fi][s.se] = '@', s.fi++, s.se++;
// F
s = {1 + n + 1, 1 + n + 1 + 2 * n + 3 + n + 1 + 1};
for(int k = 1; k <= 2 * n + 3; k++) {
ch[s.fi][s.se] = ch[s.fi + n + 1][s.se] = '@';
s.se++;
}
//Print();
// L
s = {4 * n + 5 - n - 1, 1 + n + 1 + 2 * n + 3 + n + 1 + 1 + 2 * n + 3 + n + 1};
for(int k = 1; k <= 2 * n + 3; k++) {
ch[s.fi][s.se] = '@';
s.se++;
}
//Print();
// S
s = {1 + n + 1, 1 + n + 1 + 2 * n + 3 + n + 1 + 1 + 2 * n + 3 + n + 1 + 2 * n + 3 + n + 1};
for(int k = 1; k <= 2 * n + 3; k++) {
ch[s.fi][s.se] = ch[s.fi + n + 1][s.se] = ch[s.fi + n + 1 + n + 1][s.se] = '@';
s.se++;
}
//Print();
s = {1 + n + 1, 1 + n + 1 + 2 * n + 3 + n + 1 + 1 + 2 * n + 3 + n + 1 + 2 * n + 3 + n + 1};
for(int k = 1; k <= n + 2; k++) {
ch[s.fi][s.se] = ch[s.fi + n + 1][s.se + 2 * n + 3 - 1] = '@';
s.fi++;
}
Print();
return 0;
}
作者:Orzjh
出处:https://www.cnblogs.com/Orzjh/p/16567543.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】