ps:感觉这一场的A-D都挺简单的?(虽然我没做出来),感觉只要想到点子上了就明了了。
A. Lame King(水题hh)
题意
你在点(0,0)位置上,你可以往四个方向走(上,下,左,右),但是不能连续往同一方向走两次,问你走到某一点(x,y)的代价是多少?
思路
对于点(x,y),只需要考虑max(x,y)的情况,因为大的情况走的时候可以把小的也走完全,然后考虑max(x,y)的情况的话,因为每朝向最大值的点走一格,就要多花费一个代价(除了第一次走),那么结果就是2max(x,y)-1。
ps:哦对了还有一种特殊情况需要处理,就是n==m的时候,因为每走一步都不会产生多余的代价,所以结果应该是n+m(n2)也可以。
代码
void slove( )
{
int t;
cin>>n>>m;
n=abs(n),m=abs(m);
if(n==m)cout<<n*2<<endl;
else
cout<<max(n,m)*2-1<<endl;
}
B. Vaccination
题意
在医院里有许多病人,他们都需要接种疫苗,每个人会在ai时间到达医院,并且有bi时间的耐心,即他在ai时间没有接种疫苗后,还可以等待至ai+1,ai+2,…ai+w,如果在此时间之后还没有接种疫苗,那么他就会离开。同时每袋疫苗有k支独立包装的疫苗,同时也有时间为d的保质期,如果在打开包装d时间之后,那么这包疫苗就无法使用。问你要给医院的所有人都接种好疫苗,需要最少的包装数是多少?
思路
也不难(但是一开始wa穿了qwq),就是暴力模拟一遍,可以把d+w看成整个的有效期,从第一个人打开疫苗开始,如果下一个人(我这里是从后往前)到打开疫苗的时间在这个有效期内,那么就可能使用这一袋疫苗,否则就要重新使用一袋新的。然后具体走一遍就是。
代码
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=1000000+100;
int n ,m,h;
int s[N];
bool cmp(int x ,int y ){return x>y;}
void slove( )
{
int k,d,t;
sc_int(n);
cin>>d>>k>>t;
for(int i =1;i<=n;i++)cin>>s[i];
sort(s+1,s+1+n,cmp);
int res=1,sum=d-1,time=s[1];//这里第一次就直接用了.
// for(int i =1;i<=n;i++)
// cout<<s[i]<<" \n"[i==n];
for(int i =2;i<=n;i++)
{
if(time-s[i]<=k+t&&sum>0)满足时间要求的同时要有剩余的疫苗
sum--;
else {
time=s[i];
res++;
sum=d-1;
}
}
cout<<res;
cout<<endl;
}
int main()
{
int t;
sc_int(t);
while(t--)
slove();
return 0;
}
C. Pull Your Luck
题意(很臭很长的题面)
大意就是给你一个有n个区间的,标记为0到n-1的转盘,转盘的相邻数字是递增的,即0的后面是1,1的后面是2…n-1的后面是0.现在给你一个数i,你只能对转盘使用一次操作:对于j,(1<=j<=i),使转盘向前转j+j-1+j-2+j-3+…+1个位置,然后问你能不能把转盘转到0的位置。
思路
暴力?找规律?
反正我没找到,可以试试暴力打表,发现打出来的数据在j=2n之后都是之前出现过的数据了(也可以严格证明推论?但是我不会看到佬的代码也不会讲),那么就是从min(2n,p)直接暴力搜索(这样时间复杂度就够了),看看能不能满足条件。
代码
void slove()
{
int t;
ll x, y, k;
cin >> x >> y >> k;
ll ma = k * (k + 1) / 2;
if (ma < (x - y))
{
cout << "NO\n";
return;
}
bool s=0;
for(ll i =1;i<=min(k,2*x);i++)
if((i*(i+1)/2%x)==(x-y)%x)s=1;
if(s)cout<<"YES\n";
else cout<<"NO\n";
}
D. Accommodation
题意
给你一个长度为n * m的楼房,每一层有m个窗户。每一层的有m/4个两人间(就是有两个),有m/2个单人间。对于每一个房间,只要有一个窗户是亮的,那么这个房间就被视为是正在使用的。但是每一层的单人间和双人间的布局是不限制的,即在满足条件的情况下可以任意安排双人间单人间的位置。现在给你n*m个窗户的亮度情况,问你正在使用的房间的最多和最少的个数是多少?
思路
因为每一层楼的房间互不影响,那么可以从每一层的角度来考虑问题。那么对于每一层,因为双人间和单人间的房间数是一样的,那么我们可以通过先构造双人间的情况然后剩下的房间情况就都是双人间的。
对于最少使用房间的的个数:那么就是双人间要尽可能的两个窗户都是亮的,纪录这个情况的综合sum,如果不能满足这个条件的那么要么就是不被使用,要么就是只亮一个,那么结果就是亮sum+的灯总数-sum*2。
对于最多使用房间的个数:那么双人间要尽可能的只有一个以内的房间亮,同样纪录一下然后保存答案即可。
代码
void slove( )
{
cin>>n>>m;
int res=0,ress=0;
while(n--)
{
string str;
cin>>str;
int x=0,y=0;
for(int i =0;i<m;i++)
{
if(str[i]=='1')x++;//纪录有多少灯是亮的
else y++;
}
int sum=0;
for(int i =0;i<m;i++)
{
if(str[i]=='1'&&str[i+1]=='1'&&sum<m/4&&i+1<m)
{
sum++;
i++;
}
}
int ssum=0;
for(int i =0;i<m;i++)
{
if((str[i]!='1'||str[i+1]!='1')&&i+1<m&&ssum<m/4)
{
ssum++;
i++;
}
}
// cout<<sum<<endl;
res+=sum+(x-sum*2),ress+=x-(m/4-ssum);//这里ress是看有多少个只有亮度1的双人间
}
cout<<res<<" "<<ress<<endl;
}
ps:这次题解写的好慢,因为,,,,摸了!