杭州电子科技大学计算机学院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;
}
标签:now,min,max,电子科技,题解,Debug,程序设计,include,define 来源: https://www.cnblogs.com/2017py/p/12733098.html