zhber
有好多做过的题没写下来,如果我还能记得就补吧

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


*/
posted on 2018-02-02 18:00  zhber  阅读(766)  评论(0编辑  收藏  举报