比赛地址
[A]Alarm Clock
题意
给定一个数字时钟的显示方式,然后给出显示屏上高亮的短横的总数,求可能的时间是多少。
题解
签到题
代码
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
int ans[100];
int pan(int a) {
if (a == 0) return 6;
if (a == 1) return 2;
if (a == 2) return 5;
if (a == 3) return 5;
if (a == 4) return 4;
if (a == 5) return 5;
if (a == 6) return 6;
if (a == 7) return 3;
if (a == 8) return 7;
if (a == 9) return 6;
return 1;
}
int main(){
freopen("alarm.in", "r", stdin);
freopen("alarm.out", "w", stdout);
int nowans, n;
memset(ans, -1, sizeof(ans));
for (int i = 0; i < 24; i++) {
for (int j = 0; j < 60; j++) {
nowans = 0;
nowans += pan(i%10);
nowans += pan(i/10);
nowans += pan(j%10);
nowans += pan(j/10);
ans[nowans] = i*100+j;
}
}
scanf("%d", &n);
if (ans[n] == -1) {
printf("Impossible");
return 0;
}
printf("%02d:%02d", ans[n]/100, ans[n]%100);
return 0;
}
[B]Buffcraft
题意
给出一个角色的初始生命,以及所能携带的道具总数。有两种道具,一种是直接增加生命上限的,另一种是按百分比增加生命上限。然后每种道具各有一定的数量。每个道具都有一个参数,表示其作用的效果是多少。求怎样携带道具,可以使生命上限最高。
题解
和校赛个人综合赛的一道题特别像。原题找不到了QAQ回头再补
贪心。
首先对两种道具按照作用效果从大到小排序,然后枚举道具总数的分配方式即可。
代码
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#define N 100010
#define l(x) (x<<1)
#define r(x) ((x<<1)+1)
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
int n,k,b,c1,c2,i;
struct Data{
LL x,id;
}a[N],p[N];
inline bool cmp(Data x,Data y){return x.x>y.x;}
inline int Abs(int x){return (x<0)?-x:x;}
inline void Swap(int &a,int &b){a^=b^=a^=b;}
inline int Min(int a,int b){return (a<b)?a:b;}
inline LL Max(LL a,LL b){return (a>b)?a:b;}
inline int read(){
int p=0; char c=getchar();
while (c<48||c>57) c=getchar();
while (c>=48&&c<=57) p=(p<<1)+(p<<3)+c-48,c=getchar();
return p;
}
inline void Work(){
int i=0,j=0,Ans=0;
LL s=0,S=100;
double ss=0,SS=0,cnt=0;
int head=0,tail=Min(c2,k);
for (i=1;i<=Min(c2,k);i++) S+=p[i].x;
if (S>0) SS=log(S); else SS=-10000000;
s=b;
if (k>c2)
for (i=1;i<=k-c2;i++) s+=a[i].x,head=i;
head++;
if (s>0) ss=log(s); else ss=-10000000;
cnt=ss+SS; Ans=head-1;
for (i=1;i<=k;i++){
S-=p[tail--].x; s+=a[head++].x;
if (S>0) SS=log(S); else SS=-10000000;
if (s>0) ss=log(s); else ss=-10000000;
if (ss+SS>cnt){
cnt=ss+SS; Ans=head-1;
}
if (head>c1||tail<=0) break;
}
cout<<Ans<<" "<<Min(c2,k-Ans)<<endl;
for (i=1;i<=Ans;i++) printf("%d ",a[i].id);
if (Ans) cout<<endl;
for (i=1;i<=Min(c2,k-Ans);i++) printf("%d ",p[i].id);
}
int main(){
freopen("buffcraft.in","r",stdin);
freopen("buffcraft.out","w",stdout);
scanf("%d%d%d%d",&b,&k,&c1,&c2);
if (c1+c2<=k){
cout<<c1<<" "<<c2<<endl;
for (i=1;i<=c1;i++) printf("%d ",i);
if (c1) cout<<endl;
for (i=1;i<=c2;i++) printf("%d ",i);
return 0;
}
for (i=1;i<=c1;i++) scanf("%d",&a[i].x),a[i].id=i;
for (i=1;i<=c2;i++) scanf("%d",&p[i].x),p[i].id=i;
sort(a+1,a+1+c1,cmp); sort(p+1,p+1+c2,cmp);
Work();
return 0;
}
[D]Digits
题意
给出一个数n,求n个数字的和,要求是这n个数的各位数字之和必须相等,且总和最小。
题解
签到题
代码
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#define l(x) (x<<1)
#define r(x) ((x<<1)+1)
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
int n,i,j;
LL Ans,cnt;
vector <int> v[1100];
inline int Abs(int x){return (x<0)?-x:x;}
inline void Swap(int &a,int &b){a^=b^=a^=b;}
inline LL Min(LL a,LL b){return (a<b)?a:b;}
inline LL Max(LL a,LL b){return (a>b)?a:b;}
inline int read(){
int p=0; char c=getchar();
while (c<48||c>57) c=getchar();
while (c>=48&&c<=57) p=(p<<1)+(p<<3)+c-48,c=getchar();
return p;
}
inline void Ready(){
int i=0,x=0,sum=0;
for (i=1;i<=10000000;i++){
x=i; sum=0;
while (x){
sum+=x%10; x/=10;
}
v[sum].push_back(i);
}
}
int main(){
freopen("digits.in","r",stdin);
freopen("digits.out","w",stdout);
scanf("%d",&n);
Ready();
Ans=(LL)1000000000000;
for (i=1;i<=1000;i++){
cnt=0;
if (v[i].size()<n) continue;
for (j=1;j<=n;j++) cnt+=(LL)v[i][j-1];
if (cnt<Ans) {
Ans=cnt;
}
}
cout<<Ans<<endl;
return 0;
}
[G]Grave
题意
给出两个矩形的坐标,两个矩形是包含的关系。再给出另一个矩形的长宽信息,问能否把这个矩形塞到大矩形里面而且和这两个矩形不相交。
题解
签到题
代码
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstdint>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#define IL inline
#define LL long long
#define ULL unsigned LL
#define GC getchar()
#define PC putchar
#define _Q_(x) {register char _c=GC,_v=1;for(x=0;_c<48||_c>57;_c=GC)if(_c==45)_v=-1;
#define _H_(x) for(;_c>=48&&_c<=57;x=(x<<1)+(x<<3)+_c-48,_c=GC);if(_v==-1)x=-x;}
#define sc(x) _Q_(x)_H_(x)
#define se(x) _Q_(x)else if(_c==EOF)return 0;_H_(x)
#define _G1(_1) int _1;sc(_1)
#define _G2(_1,_2) int _1,_2;sc(_1)sc(_2)
#define _G3(_1,_2,_3) int _1,_2,_3;sc(_1)sc(_2)sc(_3)
#define _gG(_1,_2,_3,_get, ...) _get
#define get(...) _gG(__VA_ARGS__,_G3,_G2,_G1, ...)(__VA_ARGS__)
#define F(i,l,r) for(int i=(l);i<(r);++i)
template<class T>
void UPRT(const T _){if(_>=10)UPRT(_/10);PC(_%10+48);}
#define UPL(_) UPRT(_),PC(10)
template<class T>
void PRT(const T _){if(_<0){PC(45),UPRT<ULL>(-(ULL)_);return;}if(_>=10)PRT(_/10);PC(_%10+48);}
#define PL(_) PRT(_),PC(10)
constexpr int MN(1e6+7);
int main()
{
freopen("grave.in", "r", stdin);
freopen("grave.out", "w", stdout);
LL bx1, bx2, by1, by2;
LL sx1, sx2, sy1, sy2;
LL w, h;
sc(bx1)sc(by1)
sc(bx2)sc(by2)
sc(sx1)sc(sy1)
sc(sx2)sc(sy2)
sc(w)sc(h)
bool ok = false;
LL ww = bx2-bx1, hh = by2-sy2;
ok |= (ww >= w && hh >= h);
ww = sx1-bx1, hh = by2-by1;
ok |= (ww >= w && hh >= h);
ww = bx2-bx1, hh = sy1-by1;
ok |= (ww >= w && hh >= h);
ww = bx2-sx2, hh = by2-by1;
ok |= (ww >= w && hh >= h);
puts(ok ? "Yes" : "No");
return 0;
}
[I]Instruction
题意
给出一个铁路网的部署情况,铁路网由两种部件构成,一种是岔道,岔道有一种输入轨道和两种输出轨道模式,输入和输出都可以是另外一个岔道。一开始,岔道的输出轨道模式自动调节成连接编号更小的下一个部件。一种是终点站台,站台只有一种输入轨道,表示其连接向一个岔道的输出。然后给出m列火车的发车信息,这些火车会从起点出发,驶向终点站台。求修改岔道的方案,使得火车都可以驶向终点。
题解
大模拟。预处理出铁路网(其实是铁路树),然后按时间模拟每个火车的行驶情况。需要改变岔道就记录下来即可。
代码
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#define N 10010
#define l(x) (x<<1)
#define r(x) ((x<<1)+1)
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
int n,sw,pl,i,x,m,y,j;
int fa[N],k[N],id[N],X[N],rr[N],rrr[N];
int head[N],w[N];
int t[100010];
char c[110][110],cc[110][110],ss[110];
struct Data{
int t,x;
};
vector <int> son[N],z[N],re;
vector <Data> Ans;
inline int Abs(int x){return (x<0)?-x:x;}
inline void Swap(int &a,int &b){a^=b^=a^=b;}
inline LL Min(LL a,LL b){return (a<b)?a:b;}
inline int Max(int a,int b){return (a>b)?a:b;}
inline LL read(){
LL p=0; char c=getchar();
while (c<48||c>57) c=getchar();
while (c>=48&&c<=57) p=(p<<1)+(p<<3)+c-48,c=getchar();
return p;
}
inline void Ready(int x){
int i=0,y=0,p=0,yy=0,pp=0;
if (!son[x].size()) return;
if (!x){
Ready(son[x][0]);
return;
}
k[x]=Min(son[x][0],son[x][1]);
Ready(son[x][0]); Ready(son[x][1]);
}
inline void Find(int x){
re.push_back(x);
if (!x) return;
Find(fa[x]);
}
inline void Work(){
int i=0,x=0,to=0,no=0;
re.clear();
for (i=0;i<=20000;i++){
for (j=0;j<re.size();j++){
x=re[j];
if (!x) continue;
no=w[x]; to=z[x][++head[x]];
if (k[no]!=to) {
k[no]=to; Ans.push_back((Data){i,no});
}
w[x]=to;
if (head[x]>=z[x].size()-1) re[j]=0;
}
if (t[i]) re.push_back(t[i]),w[t[i]]=z[t[i]][1],head[t[i]]=1;
}
}
int main(){
freopen("instruction.in","r",stdin);
freopen("instruction.out","w",stdout);
scanf("%d",&n);
sw=0; pl=0;
for (i=1;i<=n;i++){
scanf("%s",&c[i]);
if (c[i][0]=='s') {
scanf("%d",&X[i]);
} else {
scanf("%d%s",&X[i],&cc[i]);
}
}
for (i=1;i<=n;i++){
if (c[i][0]=='s') {
fa[i]=X[i]; son[X[i]].push_back(i);
} else {
fa[i]=X[i]; son[X[i]].push_back(i);
id[cc[i][0]-'a'+1]=i;
}
}
Ready(0);
scanf("%d",&m);
for (i=1;i<=m;i++){
scanf("%d%s",&x,&ss);
y=id[ss[0]-'a'+1];
re.clear();
Find(y);
for (j=re.size()-1;j>=0;j--) z[i].push_back(re[j]);
t[x]=i;
}
Work();
cout<<Ans.size()<<endl;
for (i=0;i<Ans.size();i++)
printf("%d %d\n",Ans[i].x,Ans[i].t);
return 0;
}
[J]Joy of Flight
题意
给出二维平面上飞机的起点坐标和终点坐标,以及速度的控制范围。然后已知每一秒的风向信息(由一个平面向量表示)。飞机的行驶方向便是速度向量和风向向量的合成。求飞机飞向终点的速度调整方案。
题解
签到题
代码
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#define IL inline
#define LL long long
#define ULL unsigned LL
#define GC getchar()
#define PC putchar
#define _Q_(x) {register char _c=GC,_v=1;for(x=0;_c<48||_c>57;_c=GC)if(_c==45)_v=-1;
#define _H_(x) for(;_c>=48&&_c<=57;x=(x<<1)+(x<<3)+_c-48,_c=GC);if(_v==-1)x=-x;}
#define sc(x) _Q_(x)_H_(x)
#define se(x) _Q_(x)else if(_c==EOF)return 0;_H_(x)
#define _G1(_1) int _1;sc(_1)
#define _G2(_1,_2) int _1,_2;sc(_1)sc(_2)
#define _G3(_1,_2,_3) int _1,_2,_3;sc(_1)sc(_2)sc(_3)
#define _gG(_1,_2,_3,_get, ...) _get
#define get(...) _gG(__VA_ARGS__,_G3,_G2,_G1, ...)(__VA_ARGS__)
#define F(i,l,r) for(int i=(l);i<(r);++i)
template<class T>
void UPRT(const T _){if(_>=10)UPRT(_/10);PC(_%10+48);}
#define UPL(_) UPRT(_),PC(10)
template<class T>
void PRT(const T _){if(_<0){PC(45),UPRT<ULL>(-(ULL)_);return;}if(_>=10)PRT(_/10);PC(_%10+48);}
#define PL(_) PRT(_),PC(10)
inline double dist(double x1, double y1, double x2, double y2)
{
return sqrt((x1-x2) * (x1-x2) + (y1-y2) * (y1-y2));
}
constexpr int MN(1e5+7);
double sx, sy, fx, fy;
int n, k, t[MN];
double max_v, wx[MN], wy[MN];
double get_dist(int ct)
{
int cur = 0;
double vx = 0, vy = 0;
double cur_x = fx, cur_y = fy;
F(timet, 0, ct)
{
if (cur<n && t[cur]==timet)
vx = wx[cur], vy = wy[cur], ++cur;
cur_x -= vx;
cur_y -= vy;
}
return dist(cur_x, cur_y, sx, sy);
}
int main()
{
#ifndef _KEVIN
freopen("joy.in","r",stdin);
freopen("joy.out","w",stdout);
#endif
scanf("%lf %lf %lf %lf", &sx, &sy, &fx, &fy);
scanf("%d %d %lf", &n, &k, &max_v);
F(i, 0, n)
scanf("%d %lf %lf", t+i, wx+i, wy+i);
int div;
for (div=0; div<=k+3; ++div)
if (get_dist(div) <= div * max_v)
break;
if (div > k)
return puts("No"), 0;
int cur = 0;
double vx = 0, vy = 0;
double cur_x = fx, cur_y = fy;
F(timet, 0, div)
{
if (cur<n && t[cur]==timet)
vx = wx[cur], vy = wy[cur], ++cur;
cur_x -= vx;
cur_y -= vy;
}
if (!div)
++div;
double dis = dist(cur_x, cur_y, sx, sy);
double dx = max_v * (cur_x - sx) / dis, dy = max_v * (cur_y - sy) / dis;
puts("Yes");
// 以最快速度飞到终点
cur = vx = vy = 0;
cur_x = sx, cur_y = sy;
F(timet, 0, div-1)
{
if (cur<n && t[cur]==timet)
vx = wx[cur], vy = wy[cur], ++cur;
cur_x += dx + vx;
cur_y += dy + vy;
printf("%f %f\n", cur_x, cur_y);
}
// 不动
F(timet, div, k+1)
printf("%f %f\n", fx, fy);
}
[K]Kebab House
题意
给定n段时间,每一秒钟可以有0和1两种状态。相邻两个0之间的距离必须大于t,而且给定的n段时间中,每一段的1的数量必须不小于某个定值。求度过这段时间有多少种取值方案。
题解
DP。
代码
有待补充
总结&吐槽
这场比赛的前半段时间发挥很好,罚时很少,开题速度很快。中期有一段时间有些浪费,但是节奏还可以。当做到中档题的时候,卡题现象及其严重,有些大众题目没有及时做出来,导致在后面的时间被别的队反超。以后需要加强中档题的练习,锻炼思维能力,有一些想法就及时写下来,要保证一直有人在敲代码,提升中后期效率。
本文地址: ACM暑期集训第七场