杭州电子科技大学计算机学院Debug杯程序设计竞赛
杭州电子科技大学计算机学院Debug杯程序设计竞赛
难得ak了,来写一波题解
(感觉会是很长的题解QAQ)
1001.字数补丁
题意
用若干"zsbd"来补全原串使得其大于等于指定长度
题解
暴力模拟,手速题
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define INF ~(1<<31)
#define def 100010
using namespace std;
int main()
{ long _=1,__=1,n;
string s;
for(((1)?scanf("%ld",&_):EOF);_;_--,__++){
scanf("%ld",&n);
cin>>s;
while(s.length()<n)
s+="zsbd";
cout<<s<<endl;
}
return 0;
}
1002.看电影
题意
给定一个n*m的网格,在可选的点中找两个纵坐标连续的点,使得其最接近网格中心
题解
暴力,把所有点枚举一遍
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define INF ~(1<<31)
#define def 1010
#define calc(i,j,k,l) (abs(i-k)+abs(j-l))
using namespace std;
bool mp[def][def];
int main()
{ long _=1,__=1,n,m,k,i,j,x,y,minn;
for(((1)?scanf("%ld",&_):EOF);_;_--,__++){
memset(mp,true,sizeof(mp));
scanf("%ld%ld%ld",&n,&m,&k);
for(i=1;i<=k;i++){
scanf("%ld%ld",&x,&y);
mp[x][y]=false;
}
minn=INF;
for(i=1;i<=n;i++)
for(j=1;j<m;j++)
if(mp[i][j]&&mp[i][j+1]&&calc(i,j,(n+1)/2,m/2)<minn){
minn=calc(i,j,(n+1)/2,m/2);
x=i;
y=j;
}
if(minn!=INF)
printf("(%ld,%ld) (%ld,%ld)\n",x,y,x,y+1);
else
printf("-1\n");
}
return 0;
}
1003.小C与小B的切磋
题意
有很多手牌,一些牌有价值,一些牌没有,有价值的牌只有身处手牌边缘时打出才有价值,每次可以花费\(w_i\)打掉第\(i\)张牌,问在花费不超过\(m\)的情况下能得到的最大价值
题解
显然,每次都从边缘出牌获得的价值才可能最大
因为边缘出牌的牌必定是两段连续的区间,一段从头开始,一段从尾开始,那么剩下的没出的牌肯定是一个连续的区间
于是我们可以用一个滑动区间来模拟未出牌的区间,每次保证在区间外花费不超过\(m\)的情况下,区间最短就好了
从头到尾循环一次,复杂度\(O(n)\)
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define INF ~(1<<31)
#define def 200010
using namespace std;
long a[def],b[def];
int main()
{ long _=1,__=1,n,m,i,l,r;
ll ans,sum,val,all_sum,all_val;
for(((1)?scanf("%ld",&_):EOF);_;_--,__++){
scanf("%ld%ld",&n,&m);
val=sum=0;
for(i=1;i<=n;i++){
scanf("%ld%ld",&a[i],&b[i]);
if(b[i])
scanf("%ld",&b[i]);
val+=b[i];
sum+=a[i];
}
all_sum=sum;
all_val=val;
m=all_sum-m;
ans=sum=val=0;
for(l=r=1;r<=n;r++){
sum+=a[r];
val+=b[r];
if(sum>=m)
ans=max(ans,all_val-val);
while(sum+a[r+1]-a[l]>=m){
sum-=a[l];
val-=b[l];
l++;
}
}
printf("%lld\n",ans);
}
return 0;
}
1004.小C的翻转难题
题意
定义数列的魅力值为\(\sum^{n-1}_{i=1}|a_{i+1}-a_{i}|\),允许对数列的连续的一部分进行反转操作,即让选定区间内的所有数前后顺序颠倒,求可能得到的最大魅力值
题解
ps:这应该是这场比赛最考验思维的题了,超多公式警告!!!(建议一边看一边动动笔)
如果有更简单的思路,欢迎讨论
对于一个反转操作区间\([l,r]\),很容易证明\([l+1,r-1]\)这个区间内的魅力值是不变的
那么问题变成了\(a_l, a_{l-1}, a_r, a_{r+1}\)这四个数之间的关系了
对两对单点魅力值列出算式:
令\(i=l-1, j=r\)
改变前:\(ans1=|a_i-a_{a_{i+1}}|+|a_j-a_{j+1}|\)
改变后:\(ans2=|a_i-a_j|+|a_{i+1}-a_{j+1}|\)
那么要求的就是\(ans2-ans1\)的最大值
\(ans2-ans1=|a_i-a_j|+|a_{i+1}-a_{j+1}|-|a_i-a_{a_{i+1}}|-|a_j-a_{j+1}|\)
给\(a\)排个序,可以去掉第一个绝对值,整理一下
原式\(=a_i-|a_i-a_{i+1}|+|a_{i+1}-a_{j+1}|-a_j-|a_j-a_{j+1}|\)
因为\(a_i\)和\(a_{i+1}\)以及\(a_j\)和\(a_{j+1}\)的关系飘忽不定
所以枚举\(a_{i+1}\)和\(a_{j+1}\)的大小关系
1)\(a_{i+1} > a_{j+1}\)
原式\(=(a_i+a_{i+1}-|a_i-a_{i+1}|)-(a_j+a_{j+1}+|a_j-a_{j+1}|)\)
\(=2*min(a_i, a_{i+1})-2*max(a_j,a_{j+1})\)
2)\(a_{i+1} \leq a_{j+1}\)
原式\(=(a_i-a_{i+1}-|a_i-a_{i+1}|)-(a_j-a_{j+1}+|a_j-a_{j+1}|)\)
分情况枚举一下,可知\((a_i-a_{i+1}-|a_i-a_{i+1}|) \leq 0\)且\((a_j-a_{j+1}+|a_j-a_{j+1}|) \geq 0\)
那么这种情况一定为负
综上所述,要找的就是\(2*min(a_i, a_{i+1})-2*max(a_j,a_{j+1})\)
那么既然\(i<j\)且\(a_i>a_j\),就直接从大到小排个序,然后从后往前枚举一遍,维护一下i之后的\(max(a_j,a_{j+1}\)就好了
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define INF ~(1<<31)
#define def 500010
using namespace std;
struct node{
ll x;
long y;
}a[def],b[def];
int main()
{ long _=1,__=1,n,i;
ll sum,ans,minn,maxx;
for(((1)?scanf("%ld",&_):EOF);_;_--,__++){
scanf("%ld",&n);
sum=0;
for(i=1;i<=n;i++){
scanf("%lld",&a[i].x);
a[i].y=i;
if(i>1)sum+=abs(a[i].x-a[i-1].x);
}
memcpy(b,a,sizeof(a));
sort(a+1,a+n+1,[&](node a,node b){return a.x>b.x;});
ans=0;
minn=INF;
maxx=0;
for(i=n;i>=1;i--)
if(a[i].y<n){
ans=max(ans,2*min(b[a[i].y].x,b[a[i].y+1].x)-2*minn);
minn=min(minn,max(b[a[i].y].x,b[a[i].y+1].x));
}
printf("%lld\n",sum+ans);
}
return 0;
}
5.第二届花园小学运动会
题意
在不同的距离上有很多堆东西,每次可以按照输入顺序拿走\(m\)个,如果拿满了就回到起点(距离为0的点),问拿走所有东西的需要的距离是多少
题解
看起来像一个\(dp\)或者贪心,其实认真读题会发现,顺序是固定的
那么这题就是一个模拟了
需要注意的是,每个点可能不止来回一次(在这wa了几发)
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define INF ~(1<<31)
#define def 100010
using namespace std;
ll a[def],b[def];
int main()
{ long _=1,__=1,n,m,i,now;
ll ans;
for(((1)?scanf("%ld",&_):EOF);_;_--,__++){
scanf("%ld%ld",&n,&m);
for(i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(i=1;i<=n;i++)
scanf("%lld",&b[i]);
now=m;
ans=0;
for(i=1;i<=n;i++)if(b[i]){
if(now>b[i]&&i!=n)
now-=b[i];
else{
b[i]=max(0,b[i]-now);
ans+=2*a[i]*(b[i]/m+1);
now=m-b[i]%m;
if(i==n&&now<m)
ans+=2*a[i];
}
}
printf("%lld\n",ans);
}
return 0;
}
6.阿燕的首都保卫战
题意
若干个城市按树状连接,每个点可以放置\(c_i\)个士兵,敌人进攻的时候,每个点会投入\(p_i\)个士兵,敌我士兵只能一换一,如果一个城市沦陷,剩余的敌方士兵会继续向父节点进攻,如果守城成功,守兵不会移动,问首都是否不会沦陷
题解
树状,向父节点,这两个关键词联系起来就很容易想到用dfs(没想到更高级的算法)
从下往上计算每个点的敌军数量,每个点都判断一下是否沦陷,最后判断首都
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define INF ~(1<<31)
#define def 100010
using namespace std;
vector<long>mp[def];
ll a[def],b[def];
long fa[def];
void build(long now)
{
for(auto next:mp[now])
if(next!=fa[now]){
fa[next]=now;
build(next);
a[now]+=a[next];
}
a[now]=max(0,a[now]-b[now]);
}
int main()
{ long _=1,__=1,n,i,x,y;
for(((1)?scanf("%ld",&_):EOF);_;_--,__++){
memset(fa,0,sizeof(fa));
for(i=1;i<=n;i++)
mp[i].clear();
scanf("%ld",&n);
for(i=1;i<n;i++){
scanf("%ld%ld",&x,&y);
mp[x].push_back(y);
mp[y].push_back(x);
}
for(i=1;i<=n;i++)
scanf("%lld %lld",&a[i],&b[i]);
build(1);
if(a[1])
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
7.s10的数学题
题意
计算\(\Pi_{i<j}|a_i-a_j|%m\)
题解
cf某场div2的原题,简单来说就是如果出现了两个取模相等的,那么就肯定是0,剩下的暴力解决
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define INF ~(1<<31)
#define def 100010
using namespace std;
long a[def];
int main()
{ long _=1,__=1,n,m,i,j,x;
ll sum;
for(((1)?scanf("%ld",&_):EOF);_;_--,__++){
scanf("%ld%ld",&n,&m);
for(i=1;i<=n;i++)
scanf("%ld",&a[i]);
if(n>m)
printf("0\n");
else{
sum=1;
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
sum=(sum*abs(a[i]-a[j]))%m;
printf("%lld\n",sum);
}
}
return 0;
}
8.qw的选择题
题意
考试每题乱选答案,但是答案填错了,填到了下一题的位置,每题有\(a_i\)个选项,问得分期望
题解
3种情况,分情况暴力枚举
1)\(a_i<a_{i+1}\)
得分概率\(=\frac{1}{a_i}*\frac{a_i}{a_{i+1}}\)
2)\(a_i=a_{i+1}\)
得分概率\(=\frac{1}{a_i}\)
3)\(a_i>a_{i+1}\)
得分概率\(=\frac{1}{a_{i+1}}*\frac{a_{i+1}}{a_i}\)
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define INF ~(1<<31)
#define def 100010
using namespace std;
double a[def];
int main()
{ long _=1,__=1,n,i;
double ans;
for(((1)?scanf("%ld",&_):EOF);_;_--,__++){
scanf("%ld",&n);
for(i=0;i<n;i++)
scanf("%lf",&a[i]);
ans=0;
for(i=0;i<n;i++)
if(a[i]<a[(i+1)%n])
ans+=1/a[i]*(a[i]/a[(i+1)%n]);
else if(a[i]==a[(i+1)%n])
ans+=1/a[i];
else
ans+=1/a[(i+1)%n]*(a[(i+1)%n]/a[i]);
printf("%.2lf\n",ans);
}
return 0;
}
9.张三的幸福生活
题意
输入n,问从0到n有几个数
题解
按理来说是签到题,但是看看范围知道不简单
写个阉割版高精度就好了(只需要实现+1操作)
(给最后一位+1,然后一位一位往前看是否需要进位)
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define INF ~(1<<31)
#define def 100010
using namespace std;
string deal(string s)
{ long i;
if(s.length()>=21)
return "Zhang San will never have girlfriend!";
s[s.length()-1]++;
for(i=s.length()-1;i>0;i--)
if(s[i]>'9'){
s[i]='0';
s[i-1]++;
}
if(s[0]>'9'){
s[0]='0';
s='1'+s;
}
return s;
}
int main()
{ long _=1,__=1,i;
ll maxx=1,n;
string s;
for(((1)?scanf("%ld",&_):EOF);_;_--,__++){
cin>>s;
cout<<deal(s)<<endl;
}
return 0;
}
原文地址:https://www.cnblogs.com/2017py/p/12733098.html
- Java基础——左移和右移
- 【Python环境】利用 Python、SciKit 和文本分类来实现行为分析
- LJMM平台( Linux +Jexus+MySQL+mono) 上使用MySQL的简单总结
- 判断两个单链表是否相交(有环、无环两种)
- 【数据科学家】SparkR:数据科学家的新利器
- KMP算法浅析
- Bug修复问题
- Java基础——IO流
- 来一点反射和Emit,让ORM的使用极度简化
- Java基础——集合框架
- Java基础——clone()方法浅析
- 【Python环境】matplotlib - 2D 与 3D 图的绘制
- 左求值表达式,堆栈,调试陷阱与ORM查询语言的设计
- Java基础——序列化
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python自动化(二十) | 聊聊 Python 操作PDF的几种方法(合并、拆分、水印、加密)
- C语言发展史的点点滴滴
- 我写了一个R包,简化芯片的差异分析
- 【收藏】万字解析Scipy的使用技巧!
- Python 如何使用 HttpRunner 做接口自动化测试
- Python 爬虫时,高版本 App 如何进行抓包?
- 使用 shell-operator 实现 Operator
- 我们是如何用 K8S 搞定1000个应用的测试环境
- 关于Python 3.9,那些你不知道的事
- urllib, urllib2, urllib3 都是小弟弟
- 使用 Kustomize 定制 Helm Chart
- 装逼篇 | 抖音超火的九宫格视频是如何生成的,Python 告诉你答案
- 最全总结 | 聊聊 Python 数据处理全家桶(Mysql 篇)
- 6个提升效率的pandas小技巧
- 如何用 Python 让微博热搜榜动起来