原文链接
这场只写出来了两题,赛后看了下C题,复杂的模拟题,不想写,其实是写不来 。
A 题目链接
题意
有三个怪物,每次操作可以使一个敌人扣一滴血,当此次操作为7的倍数次时,改为特殊攻击,使三个怪物都减一点血,问是否能使用特殊攻击同时消灭三个怪物。
解题思路
首先最后要用特殊攻击消灭怪物,所以三只怪物的总血量得是9的倍数,因为每7次操作,怪物一共会掉9点血。然后要考虑在是否有怪物的血量撑不到最后,意思就是会先被特殊攻击给刮死。
例如:1 3 14
是血量之和9的倍数,无论如何攻击,再第一次特殊攻击时,第一个怪物会先被消灭,所以只要当血量最低的怪物的血量>=特殊攻击的次数即可。特殊攻击的次数为血量之和/9。
代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
//#include<unordered_set>
//#include<unordered_map>
#define LL long long
#define li i<<1
#define ri i<<1|1
using namespace std;
inline LL read()
{
char c=getchar();LL x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
LL t,a[3],sum;
bool init(){
if(sum%9)
return false;
if(a[0]<sum/9)
return false;
return true;
}
int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
t=read();
while(t--){
a[0]=read();
a[1]=read();
a[2]=read();
sort(a,a+3);
sum=a[0]+a[1]+a[2];
if(init())
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
B 题目链接
题意
有一个长度为n的数组a,S为所有a[i]之和,让你构造一个数组长度为n的数组b,使得2*SUM(abs(a[i]-b[i]))<=S,且对于任何相邻的两个b[i],b[i+1],要么b[i]|b[i+1],要么b[i+1]|b[i],且b[i]>0。(SUM为求和。a|b的意思为a是b的因子。)
解题思路
比赛时想了好久,全部构造为最大值、最小值、中位数、平均数、众数,全都是错误的想法,最后才比赛快结束了才想出来。
把a数组平分为2堆,无论如何分,一定会有一堆之和>=S/2,另一堆之和<=S/2。想到这里,答案就能出来了。
构造值为这样的b数组:
1、a[2]、1、a[4]、1、a[6]、1 …
这样的数组的SUM(abs(a[i]-b[i]))=(a[1]-1)+(a[3]-1)+(a[5]-1)+…。
再构造这样的数组:
a[1]、1、a[3]、1、a[5]、1 …
这样的数组的SUM(abs(a[i]-b[i]))=(a[2]-1)+(a[4]-1)+(a[6]-1)+…。
因为之前的理论,之中一种构造一定能符合答案。
代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
//#include<chrono>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
//#include<unordered_set>
//#include<unordered_map>
#define LL long long
#define li i<<1
#define ri i<<1|1
using namespace std;
inline LL read()
{
char c=getchar();LL x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int maxn=55;
LL t,n,a[maxn],ans1[maxn],ans2[maxn];
int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
t=read();
while(t--){
n=read();
LL sum=0;
for(int i=1;i<=n;++i){
a[i]=read();
sum+=a[i];
}
for(int i=1;i<=n;++i){
if(i&1){
ans1[i]=1;
ans2[i]=a[i];
}else{
ans1[i]=a[i];
ans2[i]=1;
}
}
LL flag1=0,flag2=0;
for(int i=1;i<=n;++i){
flag1+=abs(a[i]-ans1[i]);
flag2+=abs(a[i]-ans2[i]);
}
if(2*flag1<=sum){
for(int i=1;i<=n;++i)
printf("%lld ",ans1[i]);
printf("\n");
}else if(2*flag2<=sum){
for(int i=1;i<=n;++i)
printf("%lld ",ans2[i]);
printf("\n");
}
}
return 0;
}
C 题目链接
题意
有一个机器人,在x坐标轴上行走,在0时刻时0位置。之后有n个命令:在t[i]秒时接受到命令,向目标x[i]位置走去。机器人每秒速度为1。当机器人再行走时,遇到新的指令,它将忽略此条指令。设第i条为好的指令,则满足
机器人再时间t[i]到t[i+1]时,走到过x[i]。默认t[n+1]=+∞。问一共有多少个好的指令。(被忽略的指令也能是好的指令)
写不来,模拟起来感觉很复杂。