文章目录

  • 问题 A: 鬼抓人
  • 问题 B: 坠落之前
  • 问题 C: 数据结构:树的子结点计数
  • 问题 D: 糖果合并
  • 问题 E: 幼儿园排座
  • 问题 F: 简单路径计数

(((糖豆人小专题( •̀ ω •́ )y

问题 A: 鬼抓人

根据题意,若 n≤mn \leq mn≤m,输出 unsafe
否则输出 safe
代码如下:

#include <bits/stdc++.h>
using namespace std;
signed main(){int n,m;scanf("%d%d",&n,&m);if(n<=m)puts("unsafe");else puts("safe");return 0;
}

问题 B: 坠落之前

统计所有 ddlddlddl 所需要的总时间 summ=∑i=1mAisumm=\sum_{i=1}^m A_isumm=∑i=1m​Ai​,再比较 summsummsumm 与 nnn 的大小即可
代码如下:

#include <bits/stdc++.h>
using namespace std;
int n,m,summ=0,t;
signed main(){scanf("%d%d",&m,&n);for(int i=1;i<=n;i++){scanf("%d",&t);summ+=t;}if(summ>m)puts("-1");else printf("%d\n",m-summ);return 0;
}

问题 C: 数据结构:树的子结点计数

对于每个结点最多存在一个双亲结点,在读入双亲结点时同步进行统计计数即可
代码如下:

#include <bits/stdc++.h>
using namespace std;int n,cnt[200005]={0},t;
signed main(){scanf("%d",&n);for(int i=2;i<=n;i++){scanf("%d",&t);cnt[t]++;}for(int i=1;i<=n;i++)printf("%d\n",cnt[i]);return 0;
}

问题 D: 糖果合并

找规律+等差数列求和

观察小糖果价值可得到,若选择小糖果总数不同,对答案贡献的方案数互不影响
对于选择 i(k≤i≤n+1)i(k \leq i \leq n+1)i(k≤i≤n+1) 块小糖果进行合并时,可得到的大糖果中最小重量为 i×10100+0+1+2+...+(i−1)=i×(i−1)2i \times 10^{100}+0+1+2+...+(i-1)=\frac{i \times (i-1)}{2}i×10100+0+1+2+...+(i−1)=2i×(i−1)​,最大重量为 i×10100+(n−i+1)+(n−i+2)+...+n=i×(2n−i+1)2i \times 10^{100}+(n-i+1)+(n-i+2)+...+n=\frac{i \times (2n-i+1)}{2}i×10100+(n−i+1)+(n−i+2)+...+n=2i×(2n−i+1)​,
观察提示中的样例解释同时可发现,最小重量与最大重量之间的每种重量的大糖果都可由 iii 块小糖果合并得到
故选择 i(k≤i≤n+1)i(k \leq i \leq n+1)i(k≤i≤n+1) 块小糖果时,对答案有i×(2n−i+1)2−i×(i−1)2+1=(n−i+1)×i+1\frac{i \times (2n-i+1)}{2}-\frac{i \times (i-1)}{2}+1=(n-i+1) \times i+12i×(2n−i+1)​−2i×(i−1)​+1=(n−i+1)×i+1种方案贡献数
故最终答案为∑i=kn+1((n−i+1)×i+1)\sum_{i=k}^{n+1} ((n-i+1) \times i+1)∑i=kn+1​((n−i+1)×i+1)
代码如下:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD=1e9+7;
int n,k,ans=0;
signed main(){scanf("%lld%lld",&n,&k);for(int i=k;i<=n+1;i++)ans=(ans+i*(n-i+1)%MOD+1)%MOD;printf("%lld\n",ans);return 0;
}

问题 E: 幼儿园排座

贪心+动态规划

首先明确,对于剩下所有未排好座位的小朋友,快乐指数最大的小朋友一定在可选择区间的两端对快乐总和贡献最大,故对于所有小朋友,先按照快乐指数从大到小进行排列,接着进行dpdpdp,
dp[j]dp[j]dp[j]表示左侧已有 jjj 个小朋友排好座位的最大快乐总和,则状态转移方程为:

dp[j]=max(dp[j−1]+ve[i−1].first×abs(ve[i−1].second−j),dp[j]+ve[i−1].first×abs(ve[i−1].second−(n−(i−j)+1)))dp[j]=max(dp[j-1]+ve[i-1].first \times abs(ve[i-1].second-j),dp[j]+ve[i-1].first \times abs(ve[i-1].second-(n-(i-j)+1)))dp[j]=max(dp[j−1]+ve[i−1].first×abs(ve[i−1].second−j),dp[j]+ve[i−1].first×abs(ve[i−1].second−(n−(i−j)+1)))

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD=1e9+7;
int n,dp[2005]={0},ans=0;
signed main(){scanf("%lld",&n);int t;vector<pair<int,int>>ve;for(int i=1;i<=n;i++){scanf("%lld",&t);ve.push_back({t,i});}sort(ve.begin(),ve.end(),greater<pair<int,int>>());//按照快乐指数从大到小进行排序memset(dp,-0x3f3f3f3f3f,sizeof(dp));dp[0]=0;for(int i=1;i<=n;i++){//当前给原位置为ve[i-1].second的小朋友进行排座位,其快乐指数为ve[i-1].firstfor(int j=i;j>=1;j--)dp[j]=max(dp[j-1]+ve[i-1].first*abs(ve[i-1].second-j),dp[j]+ve[i-1].first*abs(ve[i-1].second-(n-(i-j)+1)));dp[0]+=ve[i-1].first*abs(ve[i-1].second-(n-i+1));}for(int i=0;i<=n;i++)ans=max(ans,dp[i]);printf("%lld\n",ans);return 0;
}

另一个版本:(记忆化区间dp)

#include <bits/stdc++.h>
using namespace std;
const int M=2005;
long long dp[M][M],n;
struct node{long long id,val;
}a[M];
bool cmp(node pp,node qq)
{return pp.val>qq.val;
}
long long dfs(int now,int l,int r)
{//dp[l][r]表示区间[l,r]对答案的最大贡献if(l>r)return 0;if(dp[l][r]!=-1)return dp[l][r];if(now>n)return 0;long long le=dfs(now+1,l+1,r)+abs(a[now].id-l)*a[now].val;long long ri=dfs(now+1,l,r-1)+abs(a[now].id-r)*a[now].val;return dp[l][r]=max(le,ri);
}
signed main(){scanf("%lld",&n);for(int i=1;i<=n;i++){scanf("%lld",&a[i].val);a[i].id=i;}sort(a+1,a+n+1,cmp);memset(dp,-1,sizeof(dp));dfs(1,1,n);printf("%lld\n",dp[1][n]);return 0;
}

问题 F: 简单路径计数

题目要求的:

统计多少对点对(x,y)(x,y)(x,y) 满足xxx 到 yyy 的简单路径上经过至少一个颜色为 kkk 的点(x≤y)(x \leq y)(x≤y)

这有许多种情况
正难则反,此时不如将问题转换为如下:

统计多少对点对(x,y)(x,y)(x,y) 满足xxx 到 yyy 的简单路径上不经过颜色为 kkk 的点(x≤y)(x \leq y)(x≤y)

这时候比较容易想到,在统计颜色 kkk 对应答案时,我们先删去所有颜色为 kkk 的结点,则可得到若干连通块,显然连通块与连通块之间不存在简单路径不经过颜色为 kkk 的点
现在假设删点后我们得到 mmm 块连通块,第 iii 块连通块的结点数量为 szisz_{i}szi​ 则此时满足不经过颜色为 kkk 的点的简单路径数为:∑i=1mszi×(szi+1)2\sum_{i=1}^{m}\frac {sz_{i}\times (sz_{i}+1)}{2}∑i=1m​2szi​×(szi​+1)​
则此时颜色 kkk 对应答案则为 n×(n+1)2−∑i=1mszi×(szi+1)2\frac {n\times (n+1)}{2}-\sum_{i=1}^{m}\frac {sz_{i}\times (sz_{i}+1)}{2}2n×(n+1)​−∑i=1m​2szi​×(szi​+1)​

红色表示颜色为 kkk 的点,蓝色表示一个连通块

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD=1e9+7;
const int N=2e5+5;
inline int C2(int x){return x*(x+1)/2;}
int n,col[N],f[N]={0},g[N]={0},num[N]={0};
vector<int> e[N];
void dfs(int u,int fa)
{num[u]=1;int tmp=f[col[u]];for(auto v:e[u])if(v!=fa){//f[i]记录子树颜色为i的结点及其子树的总结点数f[col[u]]=0;dfs(v,u);num[u]+=num[v];//num[i]记录i及其子树的总结点数g[col[u]]+=C2(num[v]-f[col[u]]);//g[i]记录子树内无经过颜色i的简单路径总数}f[col[u]]=tmp+num[u];
}
signed main(){int u,v;scanf("%lld",&n);for(int i=1;i<=n;i++)scanf("%lld",&col[i]);for(int i=1;i<n;i++){scanf("%lld%lld",&u,&v);e[u].push_back(v);e[v].push_back(u);}dfs(1,0);for(int i=1;i<=n;i++)printf("%lld\n",C2(n)-C2(n-f[i])-g[i]);return 0;
}

北京化工大学2022-2023-1 ACM集训队每周程序设计竞赛(8)题解相关推荐

  1. 北京化工大学2022-2023-1 ACM集训队每周程序设计竞赛(11)题解

    文章目录 问题 A: 起名废柴 问题 B: 可视消息 问题 C: 虫洞旅行 问题 D: 整数化简分析 问题 E: 向量选取 问题 F: 勤劳的扫地机器人 问题 A: 起名废柴 根据题意,判断字符串 T ...

  2. 2021-2022-1 ACM集训队每周程序设计竞赛(5) - 问题 B: 跳蛙 - 题解

    传送门 分割 题目描述 输入描述 数据范围: 输出描述 样例一 输入 输出 样例二 输入 输出 提示 题目分析 AC代码 分割 CMP 跳蛙 剪切 数学? 数学! 逃离 时间限制:1秒 空间限制:12 ...

  3. BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛(10)题解

    Bob和Alice(1) 思路: 模拟即可模拟即可模拟即可 时间复杂度:O1O1O1 #include <bits/stdc++.h> #define fer(i,a,b) for(int ...

  4. 2021-2022-1 ACM集训队每周程序设计竞赛(5) - 问题 C: 剪切 - 题解

    传送门 分割 题目描述 输入描述 输出描述 样例一 输入 输出 样例二 输入 输出 提示 题目分析 AC代码 分割 CMP 跳蛙 剪切 数学? 数学! 逃离 时间限制:1秒 空间限制:128M 题目描 ...

  5. 2021-2022-2 ACM集训队每周程序设计竞赛(1) - 问题 D: 点外卖 - 题解

    题意: 有 nnn 道菜,mmm 张券,券的作用是将任意一道菜的价格变为原来的一半(下取整),且允许叠加使用,问最少花费多少钱. 思路: 每一张券最优的使用方法一定是对当前价格最高的菜使用,那么这道题 ...

  6. 北京化工大学 2022-2023-1 ACM集训队每周程序设计竞赛(7)题解

    问题 A: 幸运数字 思路:直接把N当成字符串读入,循环判断是否有一位是7就可以了. #include <bits/stdc++.h>//#include<iostream>/ ...

  7. 2021-2022-2 ACM集训队每周程序设计竞赛(1) - 问题 E: 祖玛的复仇 - 题解

    题意: 在长度为 n n n 的原字符串 S S S 找到中出现两次或两次以上的.相互之间没有重叠的连续子字符串的最大长度. 思路: 这道题的解法其实挺多的,大家可以之后多想下,我这里就只写一个最容易 ...

  8. 2021-2022-2 ACM集训队每周程序设计竞赛(1) - 问题 A: 排火车 - 题解

    题意: S u n n y Sunny Sunny之后接 C l o u d y Cloudy Cloudy, C l o u d y Cloudy Cloudy之后接 R a i n y Rainy ...

  9. 2021-2022-2 ACM集训队每周程序设计竞赛(10) - 问题 A: 还原撕碎的字条,哄笑生气的毛毛 - 题解

    传送门 还原撕碎的字条,哄笑生气的毛毛 题目描述 输入描述 输出描述 样例一 输入 输出 样例二 输入 输出 样例三 输入 输出 题目分析 AC代码 还原撕碎的字条,哄笑生气的毛毛 还原撕碎的字条,哄 ...

最新文章

  1. dev grid把一列通过选择框进行编辑
  2. word-vba-microsoft(中英文)
  3. JavaWeb学习----Cookie实现记住密码的功能
  4. textbox回车事件中拿不到text的处理办法(wpf)
  5. 拥有开源安全背景的开发员当选白宫技术总监
  6. cimiss数据_CIMISS数据下载小助手
  7. 基于隐马尔可夫模型的有监督词性标注
  8. linux设备驱动程序-i2c(1):i2c总线的添加与实现
  9. 计算机语言语法语义,程序设计语言语义
  10. GRE_××× 配置(建议选择Cisco2811路由器)
  11. android app后台运行
  12. vux移动端UI组件库
  13. autojs通用拾色器
  14. 主分区损坏diskgenius_Diskgenius硬盘分区表坏了不要紧 用软件三步就能修复
  15. 键值数据库的基本架构
  16. zabbix拓扑图添加标签信息(流量)
  17. History of Object Recognition (物体识别)
  18. GBase XDM集群服务配置
  19. 使用163邮箱发送邮件报错(554, b'DT:SPM 163 smtp3,G9xpCgCHi5RJOFVemMZ4Dw--.348S3 1582643274,please see http://ma
  20. Linux系统下的目录树结构

热门文章

  1. 超详细Tarjan算法总结,求强连通分量,割点,割边,有重边的割边
  2. 摩杜云亮相CDEC2021中国数字智能生态大会,始终专注云+数据
  3. 转载:网站分析与SEO效果的评估
  4. 初等数论的一部分结论
  5. android浪漫樱花凋零动态壁纸应用源码
  6. 传奇一键端服务器维护,烈焰炫彩传奇最终版一键服务端+启动教程+GM工具
  7. Cocos Creator 3D后期效果解决方案源码剖析--从入门到融汇贯通
  8. 微信端视频播放防被浏览器劫持
  9. 【2020东京奥运会】奥运榜单以及各国参赛运动员数据可视化~
  10. [转帖]房博士教你购房(六)