Educational Codeforces Round 100 A—D題題解
A. Dungeon
題目傳送門:
題目大意:
三個怪物具有a,b,c的血量,每發射一次炮彈,會對一個怪物造成一點傷害。每發射6次之後,第7次就是蓄力炮,對三個怪物同時造成一點傷害。問三個怪物能不能被同一個蓄力炮同時殺死。
思路:
如果a + b + c 的和sum是9的倍數原因是隻有9的倍數才可能被蓄力炮同時秒掉。且min(a,b,c)>=sum/9 ,因為在最後一次蓄力炮之前,每個怪物都不能死。
AC Code
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int sum=a+b+c;
if(sum%9) printf("NO\n");
else
{
int k=sum/9;
if(a>=k&& b>=k&&c>=k) printf("YES\n");
else printf("NO\n");
}
}
//system("pause");
return 0;
}
B. Find The Array
題目傳送門:
題目大意:
給你一個序列a,問你能不能構造出一個序列b滿足
1、bi % bi+1 == 0 或 bi+1%bi==0
2、
思路:
我們發現
X=1 + a [ 2 ] + 1 + a [ 4 ] + 1 ……
Y=a [ 1 ] + 1 + a [ 3 ] + 1 + a [ 5 ] + ……
Wx = S - X = a [ 1 ] + a [ 3 ] + a [ 5 ] + ……- n/2
Wy = S - Y =a [ 2 ] + a [ 4 ] + a [ 6 ] ……- n/2
Wx + Wy = S - n
那麼顯然Wx和Wy中必然有以一種 <= (S-n) / 2 。滿足題目要求
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL a[55];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
LL sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum=sum+a[i];
}
LL ans=0;
for(int i=1;i<=n;i=i+2)
ans=ans+a[i]-1;
if(ans*2<=sum)
{
for(int i=1;i<=n;i++)
{
if(i%2) printf("1 ");
else printf("%d ",a[i]);
}
}
else
{
for(int i=1;i<=n;i++)
{
if(i%2) printf("%d ",a[i]);
else printf("1 ");
}
}
printf("\n");
}
//system("pause");
return 0;
}
C. Busy Robot
題目傳送門:
題目大意:
有n條指令,每條指令為在ti時刻,另機器人向xi點處移動,當機器人正在移動時,機器人會忽略指令,直到完成當前指令。在[ ti , t i+1 ] 時間內,機器人移動到目標點xi,則res++。(注意包括被忽略的指令)
思路:
其實就是一個比較噁心的模擬,具體細節見程式碼。
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
LL ti[N],x[N];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld%lld",&ti[i],&x[i]);
ti[n+1]=1e10;//將n+1點的時間設定為無限大
int idx=1;
LL now=0,pos=0;
int flag=0,res=0;
while(idx<=n)
{
LL y=pos;
LL b=ti[idx];
now=ti[idx]+abs(x[idx]-pos);
if(x[idx]<pos) flag=-1;//機器人的行進方向
else flag=1;
pos=x[idx];
int k=idx+1;//中間要跳過的指令
while(ti[k]<now&&k<=n)
k++;
for(int i=idx;i<k;i++)
{
LL st=min(ti[i],now);
LL ed=min(ti[i+1],now);
LL stx=y+flag*(st-b);
LL edx=y+flag*(ed-b);
if(x[i]>=min(stx,edx)&&x[i]<=max(stx,edx)) res++;//判斷滿足條件的指令數量
}
idx=k;
}
printf("%d\n",res);
}
//system("pause");
return 0;
}
D. Pairs
題目傳送門:
題目大意
將2n個數,分成n對。其中x對進行取小操作,剩下的數進行取大操作。給你一個n個元素的序列a。問你x可以為多少種數,能得到a陣列。
思路:
知道最少有多少個數需要取小得到和最少多少個數需要取大得到。n - 兩者的數量 + 1 即為答案。
如何取呢。以計算最少需要取小的數為例。記sum為比當前的數小且不在序列a中且還未被匹配的數。
那麼如果sum>0,那麼我們就可以找一個比當前小的數,那麼當前這一對進行的就是取大的操作。(能進行取大操作就儘量取大,因為我們現在求的是取小的最少次數)
如果sum==0,那麼當前這一個數就只能找不在序列中且未匹配的最大的數,進行取小操作。
AC Code
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int a[N];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int minn=0,maxn=0;//取小的最小次數,和取大的最小次數
int sum=0;
for(int i=1;i<=n;i++)
{
sum=sum+a[i]-a[i-1]-1;
if(!sum) minn++;
else sum--;
}
a[n+1]=2*n+1;
sum=0;
for(int i=n;i>=1;i--)
{
sum=sum+a[i+1]-a[i]-1;
if(!sum) maxn++;
else sum--;
}
printf("%d\n",n-minn-maxn+1);
}
//system("pause");
return 0;
}