4516 Problem A 家庭作业

思路

设置一个无法完成的时间期限timetimetime(截止时间在此之前的作业都无法完成,即1−time1-time1−time都已被使用),设置visvisvis数组,标记第iii天是否已使用,将作业按照学分从大到小排列,按顺序遍历,若t>timet>timet>time,对于每项作业从ttt到1枚举天数,若能找到未被标记的一天,标记它并将该作业学分加入sumsumsum,若不能(1−t1-t1−t都已被使用),更新time=ttime=ttime=t,最后输出sumsumsum.

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct test{int t,s;
}a[1000005];
bool vis[700005];
bool cmp(test a,test b)
{return a.s>b.s ;
}
int main()
{int n;cin>>n;for(int i=0;i<n;++i){cin>>a[i].t>>a[i].s;}sort(a,a+n,cmp);int ti=0,sum=0;for(int i=0;i<n;++i){if(a[i].t<=ti) continue;int flag=0;for(int j=a[i].t;j>=1;--j){if(vis[j]==false){vis[j]=true;sum+=a[i].s;flag=1;break;}}if(flag==0) ti=a[i].t;}cout<<sum;}

另一个思路:用并查集查找
将每一天的fff指向自己(未被使用),若已被使用则将fff指向前一个未被使用的日子。同样将作业按照学分从大到小排列,按顺序遍历,从tttk开始找父亲,若找到x=f[x]x=f[x]x=f[x],更新f[x]f[x]f[x],标记一下返回,若x<=0x<=0x<=0,无标记返回。最后输出sumsumsum.

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct test{int t,s;
}a[1000005];
int f[700005],flag;
bool cmp(test a,test b)
{return a.s>b.s ;
}
int find(int x)
{if(x<=0) return x;else if(x==f[x]){f[x]=x-1;flag=1;return f[x];}else return f[x]=find(f[x]);
}
int main()
{for(int i=0;i<=7000005;++i)f[i]=i;int n,sum=0;cin>>n;for(int i=0;i<n;++i)cin>>a[i].t>>a[i].s; sort(a,a+n,cmp);for(int i=0;i<n;++i){flag=0;f[a[i].t]=find(a[i].t);if(flag) sum+=a[i].s;}cout<<sum;
}

4518 Problem B 糖果传递

思路

输入数据同时对小朋友的糖果数量求和,可以计算出每个小朋友最后得到aveaveave。
假设第iii个的小朋友有aiaiai颗糖果,第iii个小朋友给了第i−1i-1i−1个小朋友xixixi颗糖果,如果xi<0xi<0xi<0,说明第i−1i-1i−1个小朋友给了第iii个小朋友xixixi颗糖果,x1x1x1表示第一个小朋友给第nnn个小朋友的糖果数量。 所以最后的答案就是res=∣x1∣+∣x2∣+∣x3∣+C+∣xn∣res=|x1| + |x2| + |x3| + C+ |xn|res=∣x1∣+∣x2∣+∣x3∣+C+∣xn∣。
对于第1个小朋友,他给了第nnn个小朋友x1x1x1颗糖果,还剩a1−x1a1-x1a1−x1颗糖果;第2个小朋友又给了他x2x2x2颗糖果,所以最后第1个小朋友还剩a1−x1+x2a1-x1+x2a1−x1+x2颗糖果。
所以得 a1−x1+x2=avea1-x1+x2=avea1−x1+x2=ave。
同理,可得nnn个方程,变形得
第1个小朋友: x2=ave−a1+x1=x1−c1x2=ave-a1+x1 = x1-c1x2=ave−a1+x1=x1−c1(假设c1=a1−avec1=a1-avec1=a1−ave,下面类似)
第2个小朋友:x3=ave−a2+x2=2ave−a1−a2+x1=x1−c2x3=ave-a2+x2=2ave-a1-a2+x1=x1-c2x3=ave−a2+x2=2ave−a1−a2+x1=x1−c2
第3个小朋友:x4=ave−a3+x3=3ave−a1−a2−a3+x1=x1−c3x4=ave-a3+x3=3ave-a1-a2-a3+x1=x1-c3x4=ave−a3+x3=3ave−a1−a2−a3+x1=x1−c3
……
第n个小朋友,an−xn+x1=avean-xn+x1=avean−xn+x1=ave。
若让xixixi的绝对值之和尽量小,即∣x1∣+∣x1−x1∣+∣x1−c2∣+……+∣x1−cn−1∣|x1| + |x1-x1| + |x1-c2| + ……+ |x1-cn-1|∣x1∣+∣x1−x1∣+∣x1−c2∣+……+∣x1−cn−1∣要尽量小。注意到∣x1−ci∣|x1-ci|∣x1−ci∣的几何意义是数轴上的点x1x1x1到cicici的距离,即给定数轴上的n个点,找出一个到他们的距离之和尽量小的点,而这个点就是这些数中的中位数。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[1000005],c[1000005];
int main()
{ll n;scanf("%lld",&n);ll ave=0,res=0;for(int i=1;i<=n;++i){scanf("%lld",&a[i]);ave+=a[i];}ave=ave/n;for(int i=1;i<n;++i){c[i]=c[i-1]+a[i]-ave;}sort(c,c+n);ll  mid;if(n%2)mid=c[n/2];else mid=(c[(n-1)/2]+c[(n+1)/2])/2;for(int i=0;i<n;++i)res+=abs(c[i]-mid);printf("%lld",res);}

4696 Problem C 骑士

连接每个骑士与其厌恶的骑士,得到一个图。对于图中的每个联通块,设其节点数为kkk,则它的边数一定≤k≤k≤k(可能会有重边,所以边数可能不到kkk),这就意味着每个联通块不是一棵树就是一棵树上任意连一条边。
对于每个联通块:
①如果它是一棵树,考虑树形dpdpdp.
dp[i][j]dp[i][j]dp[i][j]表示以iii为根的子树中,iii计不计入答案(计入⇒j=1j=1j=1,不计入⇒j=0j=0j=0)的最大战斗力,转移方程为
dp[i][0]dp[i][0]dp[i][0]===∑j∈sonimax\sum_{j∈soni} max∑j∈soni​max{dp[j][0],dp[j][1]dp[j][0],dp[j][1]dp[j][0],dp[j][1]}
dp[i][1]dp[i][1]dp[i][1]===fighti+fighti+fighti+∑j∈soni\sum_{j∈soni}∑j∈soni​dp[j][0]dp[j][0]dp[j][0]
答案为
maxdp[root][0],dp[root][1]max{dp[root][0],dp[root][1]}maxdp[root][0],dp[root][1]
②如果它是一棵树加一条边,我们可以先找到联通块上的唯一的环,任意删去其中的一条边u,vu,vu,v,就得到了一棵树,鉴于u,vu,vu,v间本应有边,所以我们考虑不取uuu或不取vvv,最后取maxmaxmax就能知道联通块的答案,即分别以u,vu,vu,v为根做一遍dpdpdp,最后最大战斗力为maxmaxmax{dp[u][0],dp[v][0]dp[u][0],dp[v][0]dp[u][0],dp[v][0]}.
最终答案即为每个联通块的答案之和。
PS:注意输入时去掉重边.
参考博客,详见【BZOJ1040】【ZJOI2008】骑士 题解

学习链接

树形动态规划题集
基环树DP

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<map>
using namespace std;
vector<int>G[1000010];
int f[1000010];
bool vis[1000010];
int hte[1000010];
long long dp[1000010][2];
int n;
int u,v;
int dep[1000010];
long long ans;
void dfs(int x,int p)
{vis[x]=true;for(int i=0;i<G[x].size();i++){int y=G[x][i];if(y==p)continue;if(vis[y]){if(dep[y]<dep[x])u=x,v=y;continue;}dep[y]=dep[x]+1;dfs(y,x);}
}
void solve(int x,int p)
{dp[x][1]=f[x];dp[x][0]=0;for(int i=0;i<G[x].size();i++){int y=G[x][i];if((x==u && y==v) || (x==v && y==u) || y==p)continue;solve(y,x);dp[x][0]+=max(dp[y][0],dp[y][1]);dp[x][1]+=dp[y][0];}
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){int x;scanf("%d%d",f+i,hte+i);if(hte[hte[i]]==i)continue;G[hte[i]].push_back(i);G[i].push_back(hte[i]);}for(int i=1;i<=n;i++){if(vis[i])continue;u=v=0;dfs(i,0);long long res;if(!u && !v){solve(i,0);res=max(dp[i][0],dp[i][1]); }else{solve(u,0);res=dp[u][0];solve(v,0);res=max(res,dp[v][0]);}ans+=res;}printf("%lld",ans);return 0;
}

4697 Problem D 牧场的安排

思路

简单状压dpdpdp,二进制表示每块地的状态。
dp[i][j]dp[i][j]dp[i][j]表示第iii行jjj状态时前i行的方案数,dp[0][0]=1dp[0][0] = 1dp[0][0]=1作为边界(什么格子都不种的方案)。状态转移:如果本行的jjj状态和上一行的kkk状态不冲突,那么本行jjj状态的方案数就加上上一行kkk状态的方案数,即kkk状态可以到jjj状态。
dp[i][j]+=dp[i−1][k]dp[i][j]+=dp[i-1][k]dp[i][j]+=dp[i−1][k]
因为两块相邻的地不能种草,对数据进行预处理。当iii表示每行地的状态时,((iii<<1)&i)==0i)==0i)==0表示没有两块地相邻土地状态。用vectorvectorvector数组保存所有可能的合法状态。当iii表示这一行的状态,jjj表示上一行的状态时,iii&j==0j==0j==0就表示这两行没有地相邻。
当iii表示这一行的状态,jjj表示这一行是否可以种草的状态时,iii&j==ij==ij==i就说明i状态是可行的,假如iii&j!=ij!=ij!=i,那么就存在iii状态的某一列是1,但是这一块地本身是不能种植的。用数组s来保存这一行是否可以种草的状态。
最后统计dp[n][所有状态]dp[n][所有状态]dp[n][所有状态]的总方案数。

学习链接

状态压缩dp(状压dp)
状态压缩动态规划 状压DP

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,dp[13][401],a[13][13],s[13];
const int mod=1e8;
vector<int>v;
int main()
{int n,m;scanf("%d%d",&m,&n);for(int i=0;i<(1<<n);++i)if(((i<<1)&i)==0)v.push_back(i);for(int i=1;i<=m;++i)for(int j=0;j<n;++j)scanf("%d",&a[i][j]);for(int i=1;i<=m;++i)for(int j=0;j<n;++j)s[i]=(s[i]<<1)+a[i][j];dp[0][0]=1;for(int i=1;i<=m;++i){for(int j=0;j<v.size();++j){if((v[j]&s[i])==v[j]){for(int k=0;k<v.size();++k){if((v[k]&v[j])==0){dp[i][j]+=dp[i-1][k];dp[i][j]%=mod;}}}}}ll res=0;for(int i=0;i<v.size();++i)res=(res+dp[m][i])%mod;printf("%lld",res);
}

4924 Problem E 宝藏

思路

选择合适的方案,满足已经属于同一个联通块中的两点间不会有直接相连的第二条边,同时给定两点间连边的代价,为LLL*KKK,找到一个连边的顺序,最终使得所有点联通同时总代价最小(L∗KL*KL∗K为起点到当前点的所经过的节点数乘当前边长度)
对于每个点选或不选的状态,用状压解决。
设f[s]f[s]f[s]表示状态sss下,使得这些选择的点在同一个联通块中的最小代价,则转移方程:(从iii点转移到jjj点)
fff[1<<(j−1j-1j−1)|sss]=f[s]+dis[i]∗g[i][j]f[s]+dis[i]*g[i][j]f[s]+dis[i]∗g[i][j]
其中g[i][j]g[i][j]g[i][j]表示i,ji,ji,j两点间道路的距离,dis[i]dis[i]dis[i]表示距离iii根节点间的节点数.
搜索求出最优解,以每个点为根都进行一次dfsdfsdfs+状压dpdpdp,枚举每一个点是否被选。
参考博客,详见:[NOIP2017]宝藏-动态规划,状压dp,搜索,二进制用法模板,dfs

4767 Problem F 取石子游戏 1

思路

巴什博奕(Bash Game):
若n<=kn<=kn<=k,必然先手胜,若n=k+1n=k+1n=k+1,必然后手胜,对nnn,必有n=(k+1)∗r+sn=(k+1)*r+sn=(k+1)∗r+s,所以只要先手取走sss个,将r∗(k+1)r*(k+1)r∗(k+1)局面留给后手,则先手可以胜,若s=0s=0s=0,先手面对r∗(k+1)r*(k+1)r∗(k+1)局面,则后手胜。
即nnn%(m+1)==0m+1)==0m+1)==0. 后手胜,反之,先手胜。

学习链接

博弈论之取石子游戏的学习

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{int n,k;cin>>n>>k;if(n%(k+1)) cout<<'1';else cout<<'2';
}

4771 Problem G 巧克力棒

思路:

nimnimnim游戏
nimnimnim游戏一个很神奇的结论:对于一个局面,当且仅当a[1]xora[2]xor...xora[n]=0a[1] xor a[2] xor ...xor a[n]=0a[1]xora[2]xor...xora[n]=0时,该局面为P局面,即必败局面。
取巧克力棒:
我们取出来最长异或子序列,留给对手的是个必败局面or 他只能再拿巧克力棒,再拿巧克力棒的话局面就变成必胜了,你只需要再把局面变成a[1]xora[2]xor...xora[n]=0a[1] xor a[2] xor ...xor a[n]=0a[1]xora[2]xor...xora[n]=0.

代码

#include<bits/stdc++.h>
using namespace std;
int a[2002],panduan=0,n;
int dfs(int deep,int chang,int juge)
{if(deep==n+1){if(chang>0&&!juge)panduan=1;return 0;}dfs(deep+1,chang,juge);dfs(deep+1,chang+1,juge^a[deep]);
}
int main()
{int b,c,d,e,f,g,h,i,j,k,l,m;
for(i=1;i<=10;i++)
{cin>>n;panduan=0;
memset(a,0,sizeof(a));
for(b=1;b<=n;b++)
cin>>a[b];
dfs(1,0,0);
if(panduan)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}

学习链接

博弈论(一):Nim游戏
博弈论基础之sg函数与nim

buctoj周赛14相关推荐

  1. buctoj周赛(5)逃离(三分+思维)

    题目 可以参考官方题解 这里补充一下子集的理解: 这个题目的关键就是将问题转化成三分,如何转化这个模型呢? 分为几种情况来考虑 Δx 和 Δy 的值都增大的时候,面积 S 值一定单调递增 Δx 和 Δ ...

  2. BUCTOJ周赛(5)问题 E: 数学(线性DP+LCS)

    题目链接 (题目好像现时,不过可以参考着学一下这种类型) 这个题目是正常的线性动态规划问题,对于这个问题就是公共子序列和(LCS)的变形题目,所以就相当于是对线性dp的补充,在这再详细的解释一下动态方 ...

  3. gpt2_gpt 3,一开始是单词2 2

    gpt2 30秒摘要(30-Second Summary) Any innovative AI technology has its share of advantages and threats. ...

  4. Python 模块大全(很详细!)

    转载:.... Python的模块大全,很全,有详细介绍! 另外附Python两个教程 1. Python详细教程(廖雪峰的官方网站,语言简洁!) 2. Python 进阶教程 (Vamei) 3. ...

  5. LeetCode 第 199 场周赛(757/5231,前14.5%)

    文章目录 1. 比赛结果 2. 题目 1. LeetCode 5472. 重新排列字符串 easy 2. LeetCode 5473. 灯泡开关 IV medium 3. LeetCode 5474. ...

  6. Acwing第 14 场周赛【完结】

    目录 3821. 区间选数[难度: 简单 / 知识点:思维] 3822. 食堂排队[中 / 知识点: 模拟] 3823. 寻找字符串[难 / 知识点: KMP] 3821. 区间选数[难度: 简单 / ...

  7. ACM10.14题解

    ACM10.14题解 第一次打周赛,感觉还是比较紧张的,应该开完所有的题再做,而不是硬做,没必要硬杠英语,还是不要抱有侥幸心理,做对一定是完全理解且会,自己小心边界问题,不要瞎交. A:暴力明显不对嘛 ...

  8. LeetCode 第 30 场双周赛(477/2545,前18.7%,第2次全部通过)

    文章目录 1. 比赛结果 2. 题目 1. LeetCode 5177. 转变日期格式 easy 2. LeetCode 5445. 子数组和排序后的区间和 medium 3. LeetCode 54 ...

  9. 第二次力扣周赛:排名149 / 2046;在完赛边缘打转(总结了5点,实力还不够)

    前言: 上午10:30 - 12:00 第二次力扣周赛,最后一题也写完了,但是没有通过.完成了 3 / 4 的题,排名 149 / 2046. 赛题:https://leetcode-cn.com/c ...

最新文章

  1. 抽象类注意事项(面试常常涉及)
  2. 2021年春季学期-信号与系统-第七次作业参考答案-第九小题
  3. 【C#】C#对电子邮件的收发操作
  4. 《数据库原理与应用》(第三版)第9章 事务与并发控制 基础 习题参考答案
  5. 【渝粤题库】陕西师范大学500011 物理学史 作业(专升本)
  6. Linux日志文件总管——logrotate
  7. git 提交文件_git原理与实战
  8. HDU 1033 水题
  9. 力扣190.颠倒二进制数
  10. python3安装步骤-Mac安装python3的方法步骤
  11. logo设计好坏的12个标准
  12. Scratch3.0界面介绍
  13. 基于单片机的人体心率脉搏检测系统
  14. 探讨职业化的表达方式
  15. 风险分析(Barra风险模型)
  16. vue transition淡入淡出
  17. Vue中error ‘XXXXX‘ is not defined no-undef解决办法
  18. 阿里云Centos7修改22默认端口
  19. 第二章 MATLAB数据与矩阵
  20. GZIP压缩和解压缩不删除原始文件

热门文章

  1. 干货!任务型对话中的知识管理
  2. 大陆移动手机卡开通国际漫游(港澳台)
  3. css奇技淫巧-色彩渐变与动态渐变
  4. Linux刻录光盘win10认不到,win10系统刻录光盘光驱无法识别光盘的具体方法
  5. SaaS的中国版图,SaaS的中国问题
  6. 关于表的创建(第二次作业)
  7. mysql数据库外连_数据库外连接及MySQL实现
  8. win10安装Ubuntu16.04
  9. 黑视素照度(EML) Equivalent Melanopic Lux 计算工具
  10. 学计算机的高数学什么,儿子大一,学的计算机科学与技术,感觉高数特别难,都学不会怎么办呢?有什么好办法?...