zoukankan      html  css  js  c++  java
  • [寒假集训第一场]gym101606 2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)

    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
    ",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
    ",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
    ",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
    ",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 eq 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
    ",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)
    ",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)
    ",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)
    ",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)
    ",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)
    ",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)
    ",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
    ",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
    ",sum);
    }
    

    K Knightsbridge Rises

    留坑待补

    L Lounge Lizards

    (description)

    ​ 给一个中心点和其他(n)个带权点,如果在某个点i和中心点之间有其他点j,且(v_ileq 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
    ",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
    ",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
    
    
    */
    
  • 相关阅读:
    Linux常用命令(文件常用命令)
    Spring中的核心思想
    AOP中重要概念
    Spring框架中2种生成代理对象的方法
    python模块详解 | psutil
    Linux学习笔记 | 常见错误之无法获得锁
    python学习笔记 | 列表去重
    CentOS | python3.7安装指南
    selenium爬虫 | 爬取疫情实时动态(二)
    selenium爬虫 | 爬取疫情实时动态
  • 原文地址:https://www.cnblogs.com/zhber/p/8406358.html
Copyright © 2011-2022 走看看