• 华中农业大学第五届程序设计大赛 (7/12)


    今天实在累了,还有的题晚点补。。。。

    题目链接:http://acm.hzau.edu.cn/problemset.php?page=3

    题目:acm.hzau.edu.cn/5th.pdf

    A:Little Red Riding Hood

    题意:给你n朵花,每朵花有个权值,然后每次取花最少要间隔k朵,求权值最大;

    思路:简单dp;

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e6+10,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
    ///数组大小
    int a[N];
    ll dp[N];
    int main()
    {
        int n,k;
        int T;
        scanf("%d",&T);
        while(T--)
        {
            memset(dp,0,sizeof(dp));
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)
            if(i<=k)dp[i]=max(dp[i-1],1LL*a[i]);
            else dp[i]=max(dp[i-1],dp[i-k-1]+a[i]);
            printf("%lld
    ",dp[n]);
        }
        return 0;
    }

    D:gcd

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e6+10,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
     
    ///数组大小
    ll MOD;
    struct Matrix
    {
        ll a[2][2];
        Matrix()
        {
            memset(a,0,sizeof(a));
        }
        void init()
        {
            for(int i=0;i<2;i++)
                for(int j=0;j<2;j++)
                    a[i][j]=(i==j);
        }
        Matrix operator + (const Matrix &B)const
        {
            Matrix C;
            for(int i=0;i<2;i++)
                for(int j=0;j<2;j++)
                    C.a[i][j]=(a[i][j]+B.a[i][j])%MOD;
            return C;
        }
        Matrix operator * (const Matrix &B)const
        {
            Matrix C;
            for(int i=0;i<2;i++)
                for(int k=0;k<2;k++)
                    for(int j=0;j<2;j++)
                        C.a[i][j]=(C.a[i][j]+1LL*a[i][k]*B.a[k][j])%MOD;
            return C;
        }
        Matrix operator ^ (const ll &t)const
        {
            Matrix A=(*this),res;
            res.init();
            ll p=t;
            while(p)
            {
                if(p&1)res=res*A;
                A=A*A;
                p>>=1;
            }
            return res;
        }
    };
    int main()
    {
        Matrix base;
        base.a[0][0]=1;base.a[0][1]=1;
        base.a[1][0]=1;base.a[1][1]=0;
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n,m,p;
            scanf("%d%d%d",&n,&m,&p);
            int x=__gcd(n+2,m+2);
            MOD=p;
            if(x<=2)
                printf("%d
    ",1%p);
            else
            {
                Matrix ans=base^(x-2);
                printf("%lld
    ",(ans.a[0][0]+ans.a[0][1])%MOD);
            }
        }
        return 0;
    }
    View Code

    E:One Stroke

     题意:给你一棵二叉树,点有点权,每次往左或者往右走,求最长走的路,并且点权和小于k;

    思路:官方题解,尺取,我的写法,树上二分,

       对于一条链,枚举每个点为终点,vector存该点到根节点的前缀和,二分一下即可;

       详见代码;

      

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e6+10,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
     
    ///数组大小
    int n,ans,k,a[N];
    vector<int>v;
    void dfs(int x)
    {
        int s=0,t=v.size()-1;
        int e=v.size()-1,ansq=-1;
        while(s<=e)
        {
            int mid=(s+e)>>1;
            if(v[t]-v[mid]<=k)
            {
                ansq=mid;
                e=mid-1;
            }
            else s=mid+1;
        }
        if(v[t]<=k)ans=max(ans,t+1);
        else ans=max(ans,t-ansq);
        int z=v[v.size()-1];
        if(x*2<=n)
        {
            v.push_back(z+a[x<<1]);
            dfs(x<<1);
            v.pop_back();
        }
        if(x*2+1<=n)
        {
            v.push_back(z+a[x<<1|1]);
            dfs(x<<1|1);
            v.pop_back();
        }
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            ans=0;
            v.clear();
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            v.push_back(a[1]);
            dfs(1);
            if(ans)printf("%d
    ",ans);
            else printf("-1
    ");
        }
        return 0;
    }
    View Code

    G:Sequence Number

    题意:找出最远的i<=j&&a[i]<=a[j]的长度;

    思路:这是一道排序可以过的题,也可以rmq+二分 最快的写法可以用单调栈做到O(n)

       我是求后面的最大值后缀,二分后缀;

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e5+10,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
     
    int a[N],nex[N];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            memset(nex,0,sizeof(nex));
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int j=n;j>=1;j--)
                nex[j]=max(a[j],nex[j+1]);
            int ans=0;
            for(int i=1;i<=n;i++)
            {
                int s=i,e=n,pos=-1;
                while(s<=e)
                {
                    int mid=(s+e)>>1;
                    if(nex[mid]>=a[i])
                        pos=mid,s=mid+1;
                    else e=mid-1;
                }
                ans=max(ans,pos-i);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

     J:Color Circle

     题意:对于一个点,找长度大于4,相同字母,并且回到原点;

    思路:暴力搜索;

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e2+10,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
     
    ///数组大小
     
    char a[N][N],vis[N][N];
    int n,m,ans;
    int xx[4]={0,1,0,-1};
    int yy[4]={1,0,-1,0};
    int check(int x,int y)
    {
        if(x<=0||x>n||y<=0||y>m)
            return 0;
        return 1;
    }
    void dfs(int x,int y,int dep)
    {
        if(ans)return;
        for(int i=0;i<4;i++)
        {
            int xxx=x+xx[i];
            int yyy=y+yy[i];
            if(check(xxx,yyy)&&a[xxx][yyy]==a[x][y])
            {
                if(vis[xxx][yyy]&&dep-vis[xxx][yyy]+1>=4)
                {
                    ans=1;
                }
                else if(!vis[xxx][yyy])
                {
                    vis[xxx][yyy]=dep;
                    dfs(xxx,yyy,dep+1);
                    vis[xxx][yyy]=0;
                }
            }
        }
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            memset(vis,0,sizeof(vis));
            ans=0;
            for(int i=1;i<=n;i++)
            scanf("%s",a[i]+1);
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    dfs(i,j,1);
                    if(ans)break;
                }
                if(ans)break;
            }
            if(ans)printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
    View Code

    K:Deadline

    题意:给你n个bug,每个bug最晚修复时间,一个程序猿需要一天修复一个bug,问需要多少个程序猿才能修复成功;

    思路:开始sort一下,遍历过去超时;

       后面想想发现>=n的数根本没有必要,一个程序员总是够的,所以遍历,标记小于n的就是;

        这题只要想到思路还是很简单的,假设所有工程师每天都在修复bug,那么对天数记录bug的前缀和,O(n)得到答案max(pre[i]+i-1)/i)

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e6+10,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
    ///数组大小
    int a[N],pre[N];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            memset(pre,0,sizeof(pre));
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                if(a[i]>=N-5)continue;
                pre[a[i]]++;
            }
            int ans=1;
            for(int i=1;i<=1000000;i++)
            {
                pre[i]=pre[i]+pre[i-1];
                ans=max(ans,pre[i]/i+(pre[i]%i?1:0));
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    L:Happiness

    思路:找AB即可;

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=3e3+10,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
     
    char a[M];
    int main()
    {
        int T,cas=1;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",a+1);
            int n=strlen(a+1);
            int ans=0;
            for(int i=1;i<=n;i++)
                if(a[i]=='A'&&a[i+1]=='B')
                ans++;
            printf("Case #%d:
    %d
    ",cas++,ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    shell 编写简单的整数计算器
    信号控制
    MySQL-索引及优化整理
    Java面试-Java容器有哪些
    C语言宏定义
    值类型与引用类型的区别
    C++虚函数简介
    DNS-域名解析
    扇区,簇,块区分
    Java合并两个数组为一个新数组
  • 原文地址:https://www.cnblogs.com/jhz033/p/6754712.html
Copyright © 2020-2023  润新知