zoukankan      html  css  js  c++  java
  • Codeforces Round 607 Div2

    round 607

    A

    题意

    根据后缀判断出自哪种语言

    思路

    水题

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=1e3+3;
    
    char s[MAX];
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            scanf("%s",s);
            int len=strlen(s);
            if(s[len-2]=='p'&&s[len-1]=='o')
            {
                printf("FILIPINO
    ");
                continue;
            }
            if(s[len-4]=='d'&&s[len-3]=='e'&&s[len-2]=='s'&&s[len-1]=='u')
            {
                printf("JAPANESE
    ");
                continue;
            }
            if(s[len-4]=='m'&&s[len-3]=='a'&&s[len-2]=='s'&&s[len-1]=='u')
            {
                printf("JAPANESE
    ");
                continue;
            }
            if(s[len-5]=='m'&&s[len-4]=='n'&&s[len-3]=='i'&&s[len-2]=='d'&&s[len-1]=='a')
            {
                printf("KOREAN
    ");
                continue;
            }
        }
    }
    

    B

    题意

    给两个字符串a,ba可以交换任意一对字符(只能交换一次),问能否使得a字典序小于b

    思路

    贪心,越小的字符越前则越好,处理一下后缀min,然后从前往后判断能否交换就好了。这样一定是最优的,交换完了以后比较一下输出结果。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=5e3+3;
    
    char s[MAX],c[MAX],minn[MAX];
    int index[MAX];
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            scanf("%s%s",s,c);
            int lens=strlen(s);
            minn[lens-1]=s[lens-1];
            index[lens-1]=lens-1;
            for(int i=lens-2; i>0; i--)
            {
                index[i]=index[i+1];
                minn[i]=minn[i+1];
                if(s[i]<minn[i+1])
                {
                    index[i]=i;
                    minn[i]=s[i];
                }
            }
            for(int i=0; i<lens-1; i++)
                if(s[i]>minn[i+1])
                {
                    swap(s[i],s[index[i+1]]);
                    break;
                }
            if(strcmp(s,c)<0)
                printf("%s
    ",s);
            else
                printf("---
    ");
        }
    }
    

    C

    题意

    给一个字符串,由1,2,3组成。然后模拟一个光标,每次操作光标向右移动一位,然后把光标左右字符串切开成slsr,然后把srsl后粘贴【sl的最后一位】次。问操作x次之后此字符串的长度,输出对1e9+7取模。

    思路

    看起来好像是找规律,但是实际上暴力模拟就行了。因为每次操作只向右移动一位,所以总共需要记录的字符不超过x个。所以模拟复杂度O(x)

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=2e6+6;
    const int mod=1e9+7;
    
    char s[MAX];
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            int x;
            scanf("%d%s",&x,s+1);
            int len=strlen(s+1);
            int res=len;
            for(int i=1; i<=x; i++)
            {
                if(s[i]=='1')continue;
                int cnt=s[i]-'1';
                int cur=(res-i+mod)%mod;
                if(len<x)
                {
                    len+=cur;
                    for(int j=1;j<=cnt;j++)
                        for(int k=i+1; k<=len&&k+j*cur<=x; k++)
                            s[k+j*cur]=s[k];
                }
                res=((res+cur*cnt*1ll)%mod+mod)%mod;
            }
            printf("%d
    ",(res+mod)%mod);
        }
    }
    

    D

    题意

    给一个字符矩阵,由A,P构成。每次操作可以选1×K的一段或K×1的一段,然后向上下或左右扩展任意长度,使得扩展的那段也变成和选择的那段一样,求最少多少次可以把整个矩阵全变成A

    思路

    显然,若答案存在,则在 [0,4] 之间。然后先按行再按列判断一下就好了,先判是不是整行/列,然后判是不是在边上…………,计算答案取 min 即可。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=66;
    
    char G[MAX][MAX];
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            int n,m,res=MAX,cnt=0;
            scanf("%d%d",&n,&m);
            for(int i=0; i<n; i++)
                scanf("%s",G[i]);
            for(int i=0; i<n; i++)
            {
                bool flag1=1,flag2=0;
                for(int j=0; j<m; j++)
                {
                    flag1&=(G[i][j]=='A');
                    flag2|=(G[i][j]=='A');
                    cnt+=(G[i][j]=='A');
                }
                if(flag1)
                {
                    if(i==0||i==n-1)
                        res=min(res,1);
                    else
                        res=min(res,2);
                }
                else
                {
                    if(!flag2)continue;
                    if(G[i][0]=='A'||G[i][m-1]=='A')
                    {
                        if(i==0||i==n-1)
                            res=min(res,2);
                        else
                            res=min(res,3);
                    }
                    else
                    {
                        if(i==0||i==n-1)
                            res=min(res,3);
                        else
                            res=min(res,4);
                    }
                }
            }
            if(cnt==n*m)
            {
                printf("0
    ");
                continue;
            }
            for(int j=0; j<m; j++)
            {
                bool flag1=1,flag2=0;
                for(int i=0; i<n; i++)
                {
                    flag1&=(G[i][j]=='A');
                    flag2|=(G[i][j]=='A');
                }
                if(flag1)
                {
                    if(j==0||j==m-1)
                        res=min(res,1);
                    else
                        res=min(res,2);
                }
                else
                {
                    if(!flag2)continue;
                    if(G[0][j]=='A'||G[n-1][j]=='A')
                    {
                        if(j==0||j==m-1)
                            res=min(res,2);
                        else
                            res=min(res,3);
                    }
                    else
                    {
                        if(j==0||j==m-1)
                            res=min(res,3);
                        else
                            res=min(res,4);
                    }
                }
            }
            if(res==MAX)
                printf("MORTAL
    ");
            else
                printf("%d
    ",res);
        }
    }
    

    E

    题意

    给一棵带权树,2k个节点,将k对人分配到此树的节点上,求分配后每一对人两者距离之和的最大值和最小值。

    思路

    可以想到最大值就要每一对的两个人尽量远,最小值就是两个人尽量近。所以先求出树的重心,记为rt。则可以认为rt将树分为左右两部分(不一定是两子树),两者节点数相差1。在此模型上考虑。

    最大值就是左边的全部与右边的配对,不与自己部分的配对,可以发现最大值就是所有节点到rt的距离之和。

    最小值就是每一部分尽量自给自足。则可以想到:从rt出发开始遍历,如果子树的节点个数为偶数,那么自给自足一定优于连边到rt,所以连到此子树的边权一定没有贡献。如果子树的节点数为奇数,那么一定无法自给自足,那么此子树一定要连到rt上。然后问题可以分解成子问题。每个子问题求一个节点x的所有子树的贡献。边界为叶子节点,叶子节点一定要连到父亲节点上,也符合奇偶规律。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=2e5+5;
    typedef long long ll;
    
    struct Edge
    {
        int to,val,nxt;
    }edges[MAX<<1];
    int head[MAX],siz[MAX],mx_son_siz[MAX],n,tot,rt;
    ll minn,maxx;
    
    inline void addedge(int u,int v,int w)
    {
        edges[tot].to=v;
        edges[tot].val=w;
        edges[tot].nxt=head[u];
        head[u]=tot++;
    }
    
    void getroot(int x,int fa)
    {
        siz[x]=1;
        mx_son_siz[x]=0;
        for(int i=head[x];i!=-1;i=edges[i].nxt)
        {
            int v=edges[i].to;
            if(v==fa)continue;
            getroot(v,x);
            siz[x]+=siz[v];
            mx_son_siz[x]=max(mx_son_siz[x],siz[v]);
        }
        mx_son_siz[x]=max(mx_son_siz[x],n-siz[x]);
        if(!rt||mx_son_siz[x]<mx_son_siz[rt])
            rt=x;
    }
    
    void dfs(int x,int fa,ll sum,int w)
    {
        siz[x]=1;
        for(int i=head[x];i!=-1;i=edges[i].nxt)
        {
            int v=edges[i].to;
            if(v==fa)continue;
            dfs(v,x,sum+edges[i].val,edges[i].val);
            siz[x]+=siz[v];
        }
        if(siz[x]&1)
            minn+=w;
        maxx+=sum;
    }
    
    void init()
    {
        for(int i=1;i<=n;i++)
            head[i]=-1;
        rt=tot=0;
        minn=maxx=0ll;
    }
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            scanf("%d",&n);
            n<<=1;
            init();
            for(int i=1;i<n;i++)
            {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                addedge(u,v,w);
                addedge(v,u,w);
            }
            getroot(1,-1);
            dfs(rt,-1,0,0);
            printf("%I64d %I64d
    ",minn,maxx);
        }
    }
    
  • 相关阅读:
    微信公共服务平台开发(.Net 的实现)5-------解决access_token过期的问题
    微信公共服务平台开发(.Net 的实现)4-------语音识别
    微信公共服务平台开发(.Net 的实现)3-------发送文本消息
    微信公共服务平台开发(.Net 的实现)2-------获得ACCESSTOKEN
    微信公共服务平台开发(.Net 的实现)1-------认证“成为开发者”
    checkboxlist 横向显示,自动换行
    VMware Workstation unrecoverable error: (vmx)虚拟机挂起后无法启动问题
    ASP.NET给DataGrid,Repeater等添加全选批量删除等功能
    redis 优缺点 使用场景
    redis消息队列
  • 原文地址:https://www.cnblogs.com/cryingrain/p/12348072.html
Copyright © 2011-2022 走看看