上海大学程序设计联赛A-C E-F

从简单的开始。
C F B E A G
C:签到题。

#include<stdio.h>
#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
    double t,sum,n,flag,add;
    char c;

    cin>>t;
    while(t--)
    {
        sum=0;
        cin>>n;
        c=getchar();
        for(add=0;add<n;add++)
        {
            flag=1;
            c=getchar();
            while(c!=10)
            {
                if(c=='2'&&flag)
                {
                    flag=0;
                    sum++;
                }
                c=getchar();
            }
        }
        sum=sum/n;
        printf("%lf\n",sum);
    }
    return 0;
}

F:记每次操作的得分为p1,p2,p3...易证p1>=p2>=p3>=...,又有第一个人的得分为p1+p3+p5+...,第二个人的得分为p2+p4+p6+...故第一个人必胜。

#include<stdio.h>
#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cout<<"Yes"<<endl;
    }
    return 0;
}

B:简单的运算。写复杂了,还能简化,并且可以通过数组实现多重括号的运算。

#include<stdio.h>
#include<iostream>
#include<algorithm>

using namespace std;

char p[100002]={0};

int main()
{
    long long flag=0,sum1=0,sum2=0,add=0,n,times,k,flag2;


    char c;
    c=getchar();
    while(c!=10)
    {
        p[add++]=c;
        c=getchar();
    }
    n=add;
    for(add=0;add<n;add++)
    {
        times=0;
        flag2=0;
        if(flag==0)
        {
            if(p[add]=='C'||p[add]=='H'||p[add]=='O')
            {
                if(p[add]=='C') k=13;
                if(p[add]=='H') k=1;
                if(p[add]=='O') k=17;
                while(p[add+1]<='9'&&p[add+1]>='0')
                {
                    times=times*10;
                    times+=p[add+1]-'0';
                    add++;
                    flag2=1;
                }
                if(!flag2)
                    times=1;


                sum1+=k*times;
            }
            else if(p[add]=='(')
                flag=1;
        }
        else
        {
            if(p[add]=='C'||p[add]=='H'||p[add]=='O')
            {

                if(p[add]=='C') k=13;
                if(p[add]=='H') k=1;
                if(p[add]=='O') k=17;
                while(p[add+1]<='9'&&p[add+1]>='0')
                {
                    times=times*10;
                    times+=p[add+1]-'0';
                    add++;
                    flag2=1;
                }
                if(!flag2)
                    times=1;

                sum2+=k*times;
            }
            else if(p[add]==')')
            {
                flag=0;
                while(p[add+1]<='9'&&p[add+1]>='0')
                {
                    times=times*10;
                    times+=p[add+1]-'0';
                    add++;
                    flag2=1;
                }
                if(!flag2)
                    times=1;

                sum1+=sum2*times;
                sum2=0;
            }
        }
    }
    printf("%lld",sum1);
    return 0;
}

E:体力题。首先将十六进制转化为二进制,通过二分查找找到对应数值,再转回十六进制。

#include<stdio.h>
#include<iostream>
#include<algorithm>

using namespace std;

int s[100000],r[8],zz[32],yy;
long long j[100000];

int main()
{
    long long k[31];
    k[0]=1;
    int n,m,p,add,x,sum;
    char c;
    scanf("%d %d %d",&n,&m,&p);
    for(add=1;add<=30;add++)
    {
        k[add]=k[add-1]*2;
    }
    for(add=0;add<k[m-p];add++)
    {
        scanf("%lld",&j[add]);
        j[add]=j[add]*100000+add;
    }
    sort(j,j+k[m-p]);
    for(add=0;add<k[m-p];add++)
    {
        s[add]=j[add]%100000;
        j[add]=j[add]/100000;
    }

    cin>>x;
    while(x--)
    {
        c=getchar();
        for(add=0;add<8;add++)
        {
            c=getchar();
            if(c<='9'&&c>='0')
                r[add]=c-'0';
            else
                r[add]=c-'A'+10;
        }
        for(add=0;add<8;add++)
        {
            zz[add*4]=r[add]/8;
            if(zz[add*4]) r[add]-=8;
            zz[add*4+1]=r[add]/4;
            if(zz[add*4+1]) r[add]-=4;
            zz[add*4+2]=r[add]/2;
            if(zz[add*4+2]) r[add]-=2;
            zz[add*4+3]=r[add];
        }
        sum=0;
        for(add=0;add<32-p;add++)
        {
            sum=sum*2;
            sum+=zz[add];
        }
        for(add=0;add<k[m-p];add++)
        {
            if(sum==j[add])
                break;
        }
        if(add==k[m-p])
        {
            cout<<"interrupt!"<<endl;
            continue;
        }
        else
        {
            yy=s[add];
            for(add=0;add<32-p;add++)
            {
                if(yy>=k[32-p-add-1])
                {
                    zz[add]=1;
                    yy-=k[32-p-add-1];
                }
                else
                    zz[add]=0;
            }
            for(add=0;add<8;add++)
            {
                r[add]=0;
                for(int add2=0;add2<4;add2++)
                {
                    r[add]=r[add]*2;
                    r[add]+=zz[add*4+add2];
                }
                if(r[add]<10)
                    cout<<r[add];
                else
                    printf("%c",r[add]-10+'A');
            }
            cout<<endl;

        }
    }
    return 0;
}

A:从这题开始略有难度。首先可以将题转化为 将n/k分解成三个互质的且不为一的数。
令n=n/k。考虑n为偶数,则三个数一定为偶+奇+奇,不妨设a=2,b=n/2-1,c=n/2+1,如果b和c为偶数则b--,c++。
若n为奇数,考虑n%3==0,则a=n/3-2,b=n/3,c=n/3+2。考虑n%3==2,则a=(n-2)/3-2,b=(n-2)/3,c=(n-2)/3
+2+2。此时会出现a与c都是3的倍数的情况,则a-=2,b+=2。考虑n%3==4也就是n%3==1,a=(n-4)/3-2,b=(n-4)/3+2,c=(n-4)/3+2+2。此时会出现a与c都是3的倍数的情况,则b-=2,c+=2。
易证使用上面的方法不会出现abc不互质的情况,但需要排除abc为1的情况,即n<=9,n=11,13,17

#include<stdio.h>
#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
    long long t,n,k,a,b,c;
    cin>>t;

    while(t--)
    {
        cin>>n>>k;
        if(n%k!=0)
        {
            printf("-1 -1 -1\n");
            continue;
        }
        n=n/k;
        if(n<=9||n==11||n==13||n==17)
        {
            printf("-1 -1 -1\n");
            continue;
        }
        if(n%2==0)
        {
            a=2;
            b=(n-2)/2-1;
            c=(n-2)/2+1;
            if(b%2==0)
            {
                b--;
                c++;
            }
        }
        else
        {
            if(n%3==0)
            {
                a=n/3-2;
                b=n/3;
                c=n/3+2;
            }
            else if(n%3==2)
            {
                a=(n-2)/3-2;
                b=(n-2)/3;
                c=(n-2)/3+2+2;
                if(c%3==0)
                {
                    a-=2;
                    b+=2;
                }
            }
            else if(n%3==1)
            {
                a=(n-4)/3-2;
                b=(n-4)/3+2;
                c=(n-4)/3+2+2;
                if(c%3==0)
                {
                    b-=2;
                    c+=2;
                }
            }
        }
        a=a*k,b=b*k,c=c*k;
        printf("%lld %lld %lld\n",a,b,c);
    }
}

G:没有全过,回头再找一下疏漏。
大体思路是用dp。将问题转化在2n+1个数中取n个不相邻的数,找最大的和。假设取1 3 5 7...2n-1,那么可以将问题转化为:将两个空格插入已经取好的数列中。即:将两个空格安排再2n+1个数中间。因此设立数组zz[200020][3],其中zz[a][b]表示到第a个数已经用了b个空格的情况下,可能的最大值。
例:有1 3 6 2 4 8 9 7
zz[1][0]=1
zz[1][1]=-1e17
zz[1][2]=-1e17 注意到取第一个数的话,不可能是已经使用了一个或两个空格的状态
zz[2][0]=-1e17 注意到取第二个数的话,不可能是没有使用空格的状态
zz[2][1]=3
zz[2][2]=-1e17
zz[3][0]=zz[1][0]+6=7 不使用空格,那么应该取第1 3个数
zz[3][1]=-1e17
zz[3][2]=6 两个空格,即第1和第2都不取,直接取第3

zz[4][1]=max(zz[2][1],zz[1][0])+2 要么从1跳过来,要么从2顺延过来。换句话说,一种是取1 4,一种是取2 4,两种都是用了一个空格的情况。
zz[5][0]=zz[3][0]+4=11 取第1 3 5个数
zz[5][2]=max(zz[3][2],zz[1][0])+4 要么从1跳过来,要么从3顺延过来。换句话说,一种是取1 5,一种是取3 5,两种都是用了两个空格的情况。

...

#include<stdio.h>
#include<iostream>
#include<algorithm>

using namespace std;

long long j[200020],v[200020]={0},zz[200020][3]; 

int main()
{
    long long find(int left,int right);

    long long n,x,add,lmax,lmm,rmax,rmm,sumt,summax=-1e16;
    cin>>n>>x;

    for(add=1;add<=n;add++)
        scanf("%lld",&j[add]);

    if(n%2==0)
    {
        sumt=0;
        for(add=1;add<n;add+=2)
        {
            sumt+=j[add];
            v[add]=1;
        }
        summax=sumt;
        for(add=n-1;add>0;add-=2)
        {
            sumt-=j[add];
            sumt+=j[add+1];
            v[add]=0;
            v[add+1]=1;
            if(summax<sumt&&v[x]) summax=sumt;
        }
        cout<<summax;
        return 0;
    }
    if(x%2==0)
    {
        sumt=0;
        for(add=2;add<=n;add+=2)
            sumt+=j[add];
        summax=sumt;
        for(add=2;add<x;add+=2)
        {
            sumt-=j[add];
            sumt+=j[add-1];
            if(sumt>summax) summax=sumt;
        }
        sumt=summax;
        for(add=n-1;add>x;add-=2)
        {
            sumt-=j[add];
            sumt+=j[add+1];
            if(sumt>summax) summax=sumt;
        }
        cout<<summax;
        return 0;
    }
    if(x!=1&&x!=n)
    {
        sumt=0;
        for(add=1;add<x;add+=2)
            sumt+=j[add];
        lmax=sumt;
        sumt=0;
        for(add=x+2;add<=n;add+=2)
            sumt+=j[add];
        rmax=sumt;

        lmm=find(1,x-2);
        rmm=find(x+2,n);
        if(lmm+rmax>rmm+lmax) summax=lmm+rmax;
        else summax=rmm+lmax;
        cout<<summax+j[x];
        return 0;
    }
    if(x==n)
        cout<<find(1,n-2)+j[x];
    else
        cout<<find(3,n)+j[x];

    return 0;
}


long long find(int left,int right)
{
    long long max(long long a,long long b);
    long long max3(long long a,long long b,long long c);

    long long n=right-left+1,add,ans;

    zz[left][0]=j[left];
    zz[left+1][1]=j[left+1];
    zz[left+2][0]=zz[left][0]+j[left+2];
    zz[left+2][2]=j[left+2];

    for(add=left+3;add<=right;add++)
    {
        if((add-left)%2==1)
            zz[add][1]=max(zz[add-3][0]+j[add],zz[add-2][1]+j[add]);
        else
        {
            zz[add][0]=zz[add-2][0]+j[add];
            zz[add][2]=max3(zz[add-4][0]+j[add],zz[add-3][1]+j[add],zz[add-2][2]+j[add]);
        }   
        /*cout<<add<<endl;
        for(add2=0;add2<3;add2++) cout<<zz[add][add2]<<" ";
        cout<<endl;*/
    }

    if(n==1) return 0;
    if(n==3) return max3(j[left],j[left+1],j[left+2]);

    ans=max3(zz[right-2][0],zz[right-1][1],zz[right][2]);
    return ans;
}

long long max(long long a,long long b)
{
    if(a>=b)
        return a;
        return b;
}

long long max3(long long a,long long b,long long c)
{
    if(a>=b&&a>=c)
        return a;
    if(b>=c)
        return b;
        return c;
}
全部评论

相关推荐

联通 技术人员 总包不低于12
点赞 评论 收藏
分享
10-24 11:10
山西大学 Java
若梦难了:哥们,面试挂是很正常的。我大中厂终面挂,加起来快10次了,继续努力吧。
点赞 评论 收藏
分享
牛客717484937号:双飞硕没实习挺要命的
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务