• Gym.102059: 2018-2019 XIX Open Cup, Grand Prix of Korea(寒假gym自训第一场)


    整体来说,这一场的质量比较高,但是题意也有些难懂。

    E.Electronic Circuit

    题意:  给你N个点,M根线,问它是否是一个合法的电路。

    思路:  一个合法的电路,经过一些串联并联关系,最后有一个点是正极,一个是负极,我们就来模拟这个串联的过程即可,并联的关系会因为我们使用了set而抵消,所以可以不去管它。  模拟串联: 我们选择一个度数为2的点,删去它与两边的点u,v的连线,然后连接u-v,知道不存在度数为2的点。 最后当有两个点度数为1,而且不存在度数为大于大于2的点,则合法。

    (选择set其实比较巧妙,因为不用考虑并联。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=100010;
    set<int>S[maxn]; queue<int>q;
    int main()
    {
        int N,M,u,x,y;
        scanf("%d%d",&N,&M);
        rep(i,1,M){
            scanf("%d%d",&x,&y);
            S[x].insert(y); S[y].insert(x);
        }
        rep(i,1,N) if(S[i].size()==2) q.push(i);
        while(!q.empty()){
            u=q.front(); q.pop();
            if(S[u].size()!=2) continue;
            x=*S[u].begin(); S[u].erase(S[u].begin());
            y=*S[u].begin(); S[u].erase(S[u].begin());
            S[x].erase(u); S[y].erase(u);
            S[x].insert(y); S[y].insert(x);
            if(S[x].size()==2) q.push(x);
            if(S[y].size()==2) q.push(y);
        }
        int cnt=0,ok=1;
        rep(i,1,N) {
            if(S[i].size()==1) cnt++;
            if(S[i].size()>1) ok=0;
        }
        if(ok&&cnt==2) puts("Yes");
        else puts("No");
        return 0;
    }
    View Code

    F .Fake Plastic Trees

    题意:让你建造一棵树,使得它有N个叶子节点,而且需要满足对于每个节点,它的左子树大小等于右子树大小,或者左子树大小比右边大1。

    每次你构造一棵树,你可以选择之前构造过的树作为它的儿子。  现在让你构造不超过125棵树,满足上诉条件。

    输出的方式是,输出V,表示构造的树的多少。 接下来V上,每行表示左子树的标号和右子树的编号。 最后输出根节点的标号。

    (读了好久才懂了题意,主要是输出这里,我们构造的东西每次都是重复利用了之前的子树的。

    思路:每次除2构造即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=100010;
    int x[maxn],y[maxn],tot; map<ll,int>mp;
    void get(ll num)
    {
        if(mp.find(num)!=mp.end()) return ;
        if(num==1LL) {
            x[++tot]=-1; y[tot]=-1; mp[num]=tot;
            return ;
        }
        ll mid=num/2;
        get(num-mid); get(mid);
        tot++;  x[tot]=mp[num-mid]; y[tot]=mp[mid];
        mp[num]=tot;
    }
    int main()
    {
        int T; ll N;
        scanf("%d",&T);
        while(T--){
            scanf("%lld",&N);
            tot=-1; mp.clear(); get(N);
            printf("%d
    ",tot+1);
            rep(i,0,tot) printf("%d %d
    ",x[i],y[i]);
            printf("%d
    ",tot);
        }
        return 0;
    }
    View Code

    H .Fractions

    题意:求多少对(x,y),满足A<=x<=B ; C<=y<=D,而且(x+y)/gcd(x,y)<1000;

    思路:水题,我们枚举化简后的x'=x/gcd; y'=y/gcd;然后看有多少gcd可以在给定区间即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    int main()
    {
        ll A,B,C,D,ans=0;
        scanf("%lld%lld%lld%lld",&A,&B,&C,&D);
        rep(i,1,999)
         rep(j,1,999-i){
           if((__gcd(i,j))==1){
              //A<=ix<=B c<=jx<=D
              ll tmp=min(D/j,B/i)-max((A-1)/i,(C-1)/j);
              if(tmp>0) ans+=tmp;
           }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    I .Game on Plane

    题意:给定N个点,围成一个圈,每次玩家选择两个点连线,不得与之前连的线相交。 如果玩家连线形成了一个多边形或者没有选的点,输。

    思路:sg函数,每次连线会把大圈分为两个小圈,跑sg即可。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=5010;
    int sg[maxn],vis[maxn];
    void init()
    {
        sg[1]=0; sg[2]=1;
        rep(i,3,5000){
            rep(j,0,i-2){
                vis[sg[j]^sg[i-2-j]]=i;
            }
            rep(j,0,5000) {
                if(vis[j]!=i) { sg[i]=j; break;}
            }
        }
    }
    int main()
    {
        init();
        int T,N; scanf("%d",&T);
        while(T--){
            scanf("%d",&N);
            if(!sg[N]) puts("Second");
            else puts("First");
        }
        return 0;
    }
    View Code

    L .Timsort

    题意:给定长度为N的数组a[],Q次询问,每次给出长度L,让你按照规定跑。 每次从当前位置出发,一直跑不降序列,或者下降序列。跑完后,如果大于等于L,从下一个位置继续开始,否则要凑齐长度L,同时累计凑数的个数。

    思路:预处理,每次按照规定跑即可,因为我们可以记忆化,所以我们可以假设每次的问题是不一样的,最坏的情况下是N/1+N/2+N/3...+N/N~=NlogN,所以就ok了,想不到这一点,这个水题就跑掉了。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define rep2(i,a,b) for(int i=a;i>=b;i--)
    using namespace std;
    const int maxn=100010;
    int a[maxn],R[maxn][2],ans[maxn][2];
    int main()
    {
        int N,Q,x;
        scanf("%d",&N);
        rep(i,1,N) scanf("%d",&a[i]);
        rep2(i,N,1) {
            R[i][0]=R[i][1]=1;
            if(i+1<=N&&a[i]<=a[i+1]) R[i][0]=R[i+1][0]+1;
            if(i+1<=N&&a[i]>a[i+1]) R[i][1]=R[i+1][1]+1;
        }
        scanf("%d",&Q);
        while(Q--){
            scanf("%d",&x);
            if(ans[x][0]) printf("%d %d
    ",ans[x][0],ans[x][1]);
            else {
                int A=0,B=0;
                rep(i,1,N){
                    A++; if(i==N) break;
                    int t=R[i][a[i]>a[i+1]];
                    if(t<x){
                        if(i+x-1<=N) B+=x-t;
                        else B+=N-(i+t-1);
                        i=i+x-1;
                    }
                    else i=i+t-1;
                }
                ans[x][0]=A; ans[x][1]=B;
                printf("%d %d
    ",A,B);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    CSS属性中Display与Visibility的不同
    11
    【零基础学习iOS开发】【01-前言】01-开篇
    C#计算时间差。
    C++拷贝构造函数:浅拷贝与深拷贝
    C++:string操作函数
    文件输入输出(二):文件的操作
    文件输入输出(一):重定向
    Java中的StringBuffer
    C++中setiosflags()的用法
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10339507.html
Copyright © 2020-2023  润新知