3星场 难度在于英文题面太难读懂了QAQ 看样例猜题意的我
博客园的c++主题真丑
A Alien Sunset
\(description\)
有\(n\)个星球,每个星球自转时间不一样,所以一天的小时数\(p\)也不一样,而且日出日落时间也不一样。在模\(p\)意义下,如果日出时间是\(a\)日落时间是\(b\),那么从\(a+1\)到\(b-1\)都是白天,其他时间都是晚上。一开始所有星球时刻对齐,就是所有星球都是\(0\)时刻。在前\(1825\)天(我理解是前\(182500\)小时)找到一个时刻,使得每个星球都是晚上。
\(solution\)
直接暴力模拟,时刻增加然后每个星球自己的时刻跟着走即可。只要注意它给的是模\(p\)意义下的日出日落时刻,就是\(10\)点日出\(5\)点日落表示白天从一天\(11\)点直到第二天\(4\)点。
#include<bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define mkp make_pair
using namespace std;
int n,x,l,r;
int b[1000010];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&l,&r);
if (l<r)
{
for (int j=0;j<=1825*100;j++)
{
if (j%x>l&&j%x<r)b[j]=1;
}
}else
{
for (int j=0;j<=1825*100;j++)
{
if (j%x>l||j%x<r)b[j]=1;
}
}
}
for (int i=0;i<=1825*100;i++)if (!b[i]){printf("%d\n",i);return 0;}
puts("impossible");
}
B Breaking Biscuits
\(description\)
用两条直线截一个凸包,问直线最窄能多窄。
\(solution\)
可以\(O(n)\)旋转卡壳。
这里我直接写的\(O(n^2)\)暴力,枚举直线卡在哪一点,然后\(O(n)\)找距离最远的另一点。
#include<bits/stdc++.h>
#define maxn 50010
#define eps 1e-8
using namespace std;
typedef double data_type;
struct point{
data_type x,y;
int id;
point(){}
inline point(data_type _x,data_type _y,int _id){x=_x;y=_y;id=_id;}
inline point(data_type _x,data_type _y){x=_x;y=_y;}
inline point operator+(const point &b)const{return point(x-b.x,y-b.y);}
inline point operator-(const point &b)const{return point(x-b.x,y-b.y);}
inline data_type operator^(const point &b)const{return x*b.y-y*b.x;}//叉乘
inline data_type operator*(const point &b)const{return x*b.x-y*b.y;}//点乘
inline bool operator<(const point &b)const{return x<b.x||x==b.x&&y<b.y;}
}p[maxn];
inline data_type sqr_dist(const point a,point b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
inline double dist(const point a,point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
inline bool jijiao_cmp(const point &a,const point &b)//顺时针
{
data_type tmp=(a-p[1])^(b-p[1]);
if (tmp<-eps)return 0;if (tmp>eps)return 1;
return sqr_dist(p[1],a)<sqr_dist(p[1],b);
}
inline double calc(point a,point b,point c)
{
return fabs(((b-a)^(c-a))/dist(a,b));
}
int zhan[maxn],top;
int n;
inline void graham(int n)
{
top=0;
for (int i=2;i<=n;i++)if (p[i]<p[1])swap(p[i],p[1]);
sort(p+2,p+n+1,jijiao_cmp);
for(int i=1;i<=n;i++)
{
while (top>1&&((p[zhan[top]]-p[zhan[top-1]])^(p[i]-p[zhan[top-1]]))<=0)top--;
zhan[++top]=i;
}
int now=n-1;while (now>=1&&((p[now]-p[1])^(p[zhan[top]]-p[1]))==0)zhan[++top]=now--;
}
inline void work()
{
for (int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
graham(n);
n=top;
double ans=1<<30,cal2;
for (int i=1;i<=n;i++)
{
cal2=0;
int nex=i+1;if (nex==n+1)nex=1;
for (int j=1;j<=n;j++)
if (j!=i&&j!=nex)
{
cal2=max(cal2,calc(p[zhan[i]],p[zhan[nex]],p[zhan[j]]));
}
ans=min(ans,cal2);
}
printf("%.8f\n",ans);
}
int main()
{
while (~scanf("%d",&n)&&n)work();
}
/*
4
0 0
5 0
5 2
0 2
6
81444 14017
80944 13517
81127 12834
81810 12651
82310 13151
82127 13834
8
197 239
208 246
221 241
250 254
220 265
211 258
198 268
163 256
*/
C Cued In
\(description\)
打桌球,每种颜色的球都有它的分数,如果上一个打的是红球这一个不能打红球。如果上一个不是红球,桌上有红球只能打红球。如果桌上有红球,那么其他颜色的球被打掉可以拿回来,而且下一次还可以统计分数。问能得到的最大分数。
\(solution\)
直接贪心,各种打球的方案的唯一差异在于拿回来的球的分数不一样。显然拿分数最大的球。
#include<bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define mkp make_pair
using namespace std;
int n,sum;
int a[30];
char s[30];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%s",s+1);
if (s[1]=='r')a[i]=1;
else if (s[1]=='y')a[i]=2;
else if (s[1]=='g')a[i]=3;
else if (s[1]=='p')a[i]=6;
else if (s[2]=='r')a[i]=4;
else if (s[3]=='u')a[i]=5;
else if (s[3]=='a')a[i]=7;
sum+=a[i];
}
sort(a+1,a+n+1);
int mx=a[n],tot=0;
for (int i=1;i<=n;i++)if (a[i]==1)tot++;
if (mx!=1)
{
sum+=tot*mx;
}else sum=1;
printf("%d\n",sum);
}
D Deranging Hat
\(description\)
给一个长度不超过\(1000\)的串\(A\),已知它被按照字典序排序了,得到新串\(B\)。现在要用不超过10000次操作从\(B\)回到\(A\)。每次操作要交换\(B\)的两个位置的字符\(B_p,B_q\),而且要保证\(B_p>B_q\)。比如样例\(A=dude\),\(B=ddeu\),第一次\((4,3)\)交换\(B_4,B_3\)得到\(ddue\),第二次交换\(B_3,B_2\)得到\(dude\)。只要输出一组方案。
\(solution\)
直接暴力统计需要修改的乱序的字母,取一个当中最大的,找到这个需要字母修改的乱序位置(显然肯定存在)然后交换。这样每次乱序的字母至少少掉一。
#include<bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define mkp make_pair
using namespace std;
int n;
char s[100100],t[100010];
int main()
{
scanf("%s",s+1);n=strlen(s+1);
for (int i=1;i<=n;i++)t[i]=s[i];
sort(t+1,t+n+1);
while (1)
{
int pos=-1,pos2=-1;
for (int i=1;i<=n;i++)
if (s[i]!=t[i])
{
if (pos==-1)pos=i;
else if (t[i]>t[pos])pos=i;
}
if (pos==-1)return 0;
for (int i=1;i<=n;i++)
if (s[i]!=t[i]&&s[i]==t[pos])pos2=i;
printf("%d %d\n",pos,pos2);
swap(t[pos],t[pos2]);
}
}
E Education
\(description\)
每一件物品有质量\(W\)和价格\(V\),要求从\(m\)件物品中买\(n\)件,这\(n\)件物品第\(i\)件的质量不少于\(s_i\),同时总价格最小。输出方案。
\(solution\)
把物品和需求都按质量从大到小排,然后枚举需求,把所有质量大等于当前需求的物品扔进堆,取个价值最小的即可。
#include<bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define mkp make_pair
#define pa pair<int,int>
using namespace std;
int n,m;
priority_queue<pa,vector<pa>,greater<pa> >q;
struct p{int v,rnk;}a[1000010]; bool operator <(p a,p b){return a.v>b.v;}
struct Q{int v,w,rnk;}b[1000010];bool operator <(Q a,Q b){return a.v>b.v;}
int ans[100100];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)scanf("%d",&a[i].v),a[i].rnk=i;
sort(a+1,a+n+1);
for (int i=1;i<=m;i++)scanf("%d",&b[i].v);
for (int i=1;i<=m;i++)scanf("%d",&b[i].w),b[i].rnk=i;
sort(b+1,b+m+1);
int now=1;
for (int i=1;i<=n;i++)
{
while (now<=m&&a[i].v<=b[now].v)
{
q.push(mkp(b[now].w,b[now].rnk));
now++;
}
if (q.empty()){puts("impossible");return 0;}
pa tp=q.top();q.pop();
ans[a[i].rnk]=tp.second;
}
for (int i=1;i<=n;i++)printf("%d ",ans[i]);
}
F Flipping Coins
\(description\)
\(n\)个硬币,一开始都是反面向上,一共投\(p\)次,每次选一个硬币重投,它取得正面和反面的概率都是\(\frac{1}{2}\)。问最优策略下投完\(p\)次之后正面向上的硬币个数的期望的最大值。必须投满\(p\)次。
\(solution\)
硬币和硬币之间没有本质区别,所以只考虑正反面的硬币各有多少个即可。最优策略肯定是只选还是反面的硬币重投。\(f[i][j]\)表示投了i次、有j个正面向上的硬币的概率。
如果\(j=n\),只能选一个正面的投,\(f[i][j]\)分别有\(\frac{1}{2}\)概率转移到\(f[i+1][j]\)和\(f[i+1][j-1]\)。
如果\(j\neq n\) ,选一个反面的投,\(f[i][j]\)分别有\(\frac{1}{2}\)的概率转移到\(f[i+1][j+1]\)和\(f[i+1][j]\)。
#include<bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define mkp make_pair
using namespace std;
int n,m;
double f[410],g[410],ans;
int main()
{
scanf("%d%d",&n,&m);
f[0]=1;
for (int i=1;i<=m;i++)
{
memset(g,0,sizeof(g));
for (int j=0;j<n;j++)
{
g[j]+=f[j]/2;
g[j+1]+=f[j]/2;
}
g[n]+=f[n]/2;
g[n-1]+=f[n]/2;
for (int j=0;j<=n;j++)f[j]=g[j];
}
for (int i=1;i<=n;i++)ans+=f[i]*i;
printf("%.8f\n",ans);
}
G GentleBots
\(description\)
两个机器人分别从(x1,y1,z1),(x2,y2,z2)出发,分别要到达(x'1,y'1,z'1),(x'2,y'2,z'2)。每次只能移动一格。要求他们不能在某个时刻处在同一格,也不能在移动过程中交换位置。
\(solution\)
如果两个机器人下一步要走到同一个点,那么让一个不动,另一个先走即可。
如果两个机器人下一步走完会交换位置,那么让其中一个绕一圈到达,另一个直接走过来,这样就成功交换位置了。
其他坑点不是很坑,可以忽略不计。
#include<bits/stdc++.h>
#define mkp(a,b,c) make_pair(make_pair(a,b),c)
#define paa pair<pair<int,int>,int>
using namespace std;
int tag1,tag2;
int sx1,sy1,sz1,ex1,ey1,ez1;
int sx2,sy2,sz2,ex2,ey2,ez2;
int nx1,ny1,nz1,nx2,ny2,nz2;
int wx1,wy1,wz1,wx2,wy2,wz2;
inline void mv(int x,int y,int z)
{
sx1+=x;sy1+=y;sz1+=z;
printf("(%d %d %d) (%d %d %d)\n",sx1,sy1,sz1,sx2,sy2,sz2);
}
inline void mv2(int x,int y,int z)
{
sx2+=x;sy2+=y;sz2+=z;
printf("(%d %d %d) (%d %d %d)\n",sx1,sy1,sz1,sx2,sy2,sz2);
}
inline void go1(int x,int y,int z)
{
if (x==1)
{
mv(0,1,0);
mv(1,0,0);
mv(1,0,0);
mv(0,-1,0);
}else if (x==-1)
{
mv(0,1,0);
mv(-1,0,0);
mv(-1,0,0);
mv(0,-1,0);
}else if (y==1)
{
mv(1,0,0);
mv(0,1,0);
mv(0,1,0);
mv(-1,0,0);
}else if (y==-1)
{
mv(1,0,0);
mv(0,-1,0);
mv(0,-1,0);
mv(-1,0,0);
}else if (z==1)
{
mv(1,0,0);
mv(0,0,1);
mv(0,0,1);
mv(-1,0,0);
}else if (z==-1)
{
mv(1,0,0);
mv(0,0,-1);
mv(0,0,-1);
mv(-1,0,0);
}
}
inline void go2(int x,int y,int z)
{
if (x==1)
{
mv2(0,1,0);
mv2(1,0,0);
mv2(1,0,0);
mv2(0,-1,0);
}else if (x==-1)
{
mv2(0,1,0);
mv2(-1,0,0);
mv2(-1,0,0);
mv2(0,-1,0);
}else if (y==1)
{
mv2(1,0,0);
mv2(0,1,0);
mv2(0,1,0);
mv2(-1,0,0);
}else if (y==-1)
{
mv2(1,0,0);
mv2(0,-1,0);
mv2(0,-1,0);
mv2(-1,0,0);
}else if (z==1)
{
mv2(1,0,0);
mv2(0,0,1);
mv2(0,0,1);
mv2(-1,0,0);
}else if (z==-1)
{
mv2(1,0,0);
mv2(0,0,-1);
mv2(0,0,-1);
mv2(-1,0,0);
}
}
int main()
{
srand(time(0));
scanf("%d%d%d%d%d%d",&sx1,&sy1,&sz1,&ex1,&ey1,&ez1);
scanf("%d%d%d%d%d%d",&sx2,&sy2,&sz2,&ex2,&ey2,&ez2);
printf("(%d %d %d) (%d %d %d)\n",sx1,sy1,sz1,sx2,sy2,sz2);
while (!(sx1==ex1&&sy1==ey1&&sz1==ez1&&sx2==ex2&&sy2==ey2&&sz2==ez2))
{
nx1=nx2=ny1=ny2=nz1=nz2=0;
if (sx1-ex1)nx1=sx1<ex1?1:-1;
else if (sy1-ey1)ny1=sy1<ey1?1:-1;
else if (sz1-ez1)nz1=sz1<ez1?1:-1;
else tag1=1;
if (sx2-ex2)nx2=sx2<ex2?1:-1;
else if (sy2-ey2)ny2=sy2<ey2?1:-1;
else if (sz2-ez2)nz2=sz2<ez2?1:-1;
else tag2=1;
wx1=sx1+nx1;wy1=sy1+ny1;wz1=sz1+nz1;
wx2=sx2+nx2;wy2=sy2+ny2;wz2=sz2+nz2;
if (wx1==wx2&&wy1==wy2&&wz1==wz2)
{
if (tag1)go2(nx2,ny2,nz2);
else if (tag2)go1(nx1,ny1,nz1);
else
{
sx1=wx1;sy1=wy1;sz1=wz1;
printf("(%d %d %d) (%d %d %d)\n",sx1,sy1,sz1,sx2,sy2,sz2);
}
}else if (wx1==sx2&&wy1==sy2&&wz1==sz2)
{
if (!(wx2==sx1&&wy2==sy1&&wz2==sz1))
{
sx1=wx1;sy1=wy1;sz1=wz1;
sx2=wx2;sy2=wy2;sz2=wz2;
printf("(%d %d %d) (%d %d %d)\n",sx1,sy1,sz1,sx2,sy2,sz2);
}else
{
go1(nx1,ny1,nz1);
}
}else
{
sx1=wx1;sy1=wy1;sz1=wz1;
sx2=wx2;sy2=wy2;sz2=wz2;
printf("(%d %d %d) (%d %d %d)\n",sx1,sy1,sz1,sx2,sy2,sz2);
}
}
}
H Hiker Safety
留坑待补
I Work All Day
\(description\)
给出\(T\)和\(n\)个数\(h_1...h_n\),找一个\(h_k\)使得\(T\%h_k\)最小,并且\(k\)最小。
\(solution\)
暴力。
#include<bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define mkp make_pair
using namespace std;
int n,sum,sv;
int a[30];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)scanf("%d",a+i);
scanf("%d",&sum);
sv=a[1];
for (int i=2;i<=n;i++)
{
if (sum%a[i]<sum%sv)sv=a[i];
}
printf("%d\n",sv);
}
J Just A Minim
\(description\)
一堆\(2^k\)求和。
\(solution\)
暴力。
#include<bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define mkp make_pair
using namespace std;
int n;
double sum;
int a[30];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
if (x==0)sum+=2;
if (x==1)sum++;
if (x==2)sum+=0.5;
if (x==4)sum+=0.25;
if (x==8)sum+=0.125;
if (x==16)sum+=0.0625;
}
printf("%.6f\n",sum);
}
K Knightsbridge Rises
留坑待补
L Lounge Lizards
\(description\)
给一个中心点和其他\(n\)个带权点,如果在某个点i和中心点之间有其他点j,且\(v_i\leq v_j\)则点i被挡住。问有多少个点是不被挡住的。
\(solution\)
显然只有同一个方向上的点上会存在挡住。所有点相对中心点按照极角排序,然后提出所有方向相同的点,按照到中心点的距离排个序,然后做个最长上升子序列,就是不被挡住的点个数。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define eps 1e-8
typedef ll data_type;
struct point{
data_type x,y,h;
point(){}
inline point(data_type _x,data_type _y){x=_x;y=_y;}
inline point operator+(const point &b)const{return point(x-b.x,y-b.y);}
inline point operator-(const point &b)const{return point(x-b.x,y-b.y);}
inline data_type operator^(const point &b)const{return x*b.y-y*b.x;}//叉乘
inline data_type operator*(const point &b)const{return x*b.x-y*b.y;}//点乘
inline bool operator<(const point &b)const{return x<b.x||x==b.x&&y<b.y;}
}p[1001000];
int sx,sy,n,ans;
inline data_type sqr_dist(const point a,point b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
inline double dist(const point a,point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
inline int Quad(point a)
{
if (a.x>0&&a.y>=0)return 1;
if (a.x<=0&&a.y>0)return 2;
if (a.x<0&&a.y<=0)return 3;
if (a.x>=0&&a.y<0)return 4;
}
inline data_type cmp(const point &a,const point &b,const point &c){return (b-a)^(c-a);}
inline bool jijiao_cmp(const point &a,const point &b)//顺时针
{
if (Quad(a-p[1])!=Quad(b-p[1]))return Quad(a-p[1])<Quad(b-p[1]);
data_type mmp=cmp(p[1],a,b);
if (mmp==0)return sqr_dist(p[1],a)<sqr_dist(p[1],b);;
return mmp>0;
}
int a[1000100],top,tot;
int f[1000010];
int mn[1000010];
inline int bsearch(int x,int l,int r)
{
int s=0;
while (l<=r)
{
int mid=(l+r)>>1;
if (mn[mid]<x){s=mid;l=mid+1;}
else r=mid-1;
}
return s;
}
inline void solve()
{
mn[1]=a[1];tot=1;f[1]=1;
for (int i=2;i<=top;i++)
{
int fnd=bsearch(a[i],1,tot);
if (fnd==tot)mn[++tot]=a[i];
else if (a[i]<mn[fnd+1])mn[fnd+1]=a[i];
f[i]=fnd+1;
}
ans+=tot;
}
main()
{
scanf("%lld%lld",&p[1].x,&p[1].y);
scanf("%lld",&n);n++;
for (int i=2;i<=n;i++)
{
scanf("%lld%lld%lld",&p[i].x,&p[i].y,&p[i].h);
}
sort(p+2,p+n+1,jijiao_cmp);
for (int i=2;i<=n;i++)
{
//printf(" %lld %lld %lld\n",i,p[i].x,p[i].y);
if (i==2||i!=2&&((p[i]-p[1])^(p[i-1]-p[1]))==0&&((p[i].x>p[1].x)^(p[i-1].x>p[1].x))==0)a[++top]=p[i].h;
else
{
solve();
top=1;a[top]=p[i].h;
}
}
if (top)solve();
printf("%lld\n",ans);
}
/*
0 0
24
-2 -2 1
-2 -1 1
-2 0 1
-2 1 1
-2 2 1
-1 -2 1
-1 -1 1
-1 0 1
-1 1 1
-1 2 1
0 -2 1
0 -1 1
0 1 1
0 2 1
1 -2 1
1 -1 1
1 0 1
1 1 1
1 2 1
2 -2 1
2 -1 1
2 0 1
2 1 1
2 2 1
*/