2019年华南理工大学程序设计竞赛(春季赛)报告

小六喜欢两全其美的事情,今天就正好有一个这样的机会。
小六面前有两根管子,管子里面放满了数字为1到9的小球。每次取球时,小六会先选择一根管子,再从这根管子的某一侧(左侧或右侧)取出一个球。在满足取球规则的情况下,他可以任意顺序取出所有小球。假如小六依次取出的球的编号为a1,a2,⋯,ana1,a2,⋯,an,则他最后就得到了一个形如¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯a1a2⋯ana1a2⋯an¯样的十进制数。
小六希望他的取球顺序所组成的数是最大的,你可以帮一下他吗?

输入描述:

第一行输入数据组数。T (T≤14)T (T≤14)

接下来T行,每行输入两串只含1∼91∼9的数字,表示两根管子里的小球的数字。每根管子内至少含1个小球,且数量不超过40个。

输出描述:

对每一组数据,输出一行Case #x: A,其中x是数据组数编号(从1开始),A是小六能组成的最大的数。

示例1

输入

2

123456 123456

9876346789 9854894589

输出

Case #1: 665544332211

Case #2: 99998888776655498443

 

题解:请记住一定记得string 可以比较大小。这个问题以前也做过,希望以后可以记住,不要在忘记了

AC代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int n;
    int i,j;
    string str[4];
    string ans;
    int it=0;
    int k=0;
    while(scanf("%d",&n)!=EOF)
    {
        for(k=0; k<n; k++)
        {
            cin>>str[0]>>str[1];
            str[2]=str[0];
            str[3]=str[1];
            reverse(str[2].begin(),str[2].end());
            reverse(str[3].begin(),str[3].end());
            ans="";
            int len=str[0].length()+str[1].length();
            int anslen=0;
            while(anslen<len)
            {
                string temp=str[0];
                it=0;
                for(i=0; i<4; i++)
                {
                    if(temp<str[i])
                    {
                        temp=str[i];
                        it=i;
                    }
                }
                ans=ans+str[it][0];
                str[it].erase(0,1);
                if(it==0)
                    str[2].erase(str[2].length()-1,1);
                if(it==1)
                    str[3].erase(str[3].length()-1,1);
                if(it==2)
                    str[0].erase(str[0].length()-1,1);
                if(it==3)
                    str[1].erase(str[1].length()-1,1);
                anslen++;
            }
            cout<<"Case #"<<k+1<<": "<<ans<<endl;
        }
    }
}

众所周知,在算法竞赛中,出题人对他出的题的难度往往存在错误的估计。比如出题人本想出个中等题,没想到却出成了简单题;本想出个自闭题,结果数据太水变成了签到题。因此,为了让一场比赛能有良好的体验,有一个靠谱的验题人是非常重要的。
CC出好题目后,便拿给小马哥看。不出所料,这些题目小马哥全都是看一眼就会做了。而且,小马哥觉得这些题对于参赛选手来说也太水了(5个签到题哦~)。为了避免发生全场十几个队AK这种紧急事态,小马哥决定把一道签到题改成简单题,于是便有了现在这个题目。
小马哥非常喜欢数论,尤其钟爱“最大公约数”(Greatest Common Divisor,简称GCD)这一概念,因此他打算出一道和GCD有关的题目。小马哥首先给出了含n个正整数的序列a1,a2,⋯,ana1,a2,⋯,an,然后让你考虑该序列的所有子区间的数对应的GCD值,也就是说考虑所有gcd(al,⋯,ar)gcd(al,⋯,ar)的值。显然,这样的值一共有n(n+1)2n(n+1)2个。一个中二出题人可能会让你求这n(n+1)2n(n+1)2数中第k大的数,但幸运的是,小马哥是个正经出题人,因此它只让你求这n(n+1)2n(n+1)2个数之和模109+7109+7的结果。

也就是要求下面这个式子:

ans=(∑nl=1∑nr=lgcd(al,⋯,ar))mod(109+7)ans=(∑l=1n∑r=lngcd(al,⋯,ar))mod(109+7)

小马哥在此预祝大家AK~

输入描述:

第一行是一个整数n (1≤n≤5×105)n (1≤n≤5×105),表示数的个数。

接下来一行给出n个整数,其中第i个整数aiai满足1≤ai≤1091≤ai≤109。

输出描述:

输出一行一个整数,表示ans的值。

示例1

输入

5

16 4 7 21 3

输出

72

 

题解,先求出所有数的最小公约数,然后如果有几个数的最小公约数和所有数的最小公约数相同,那么就不用在判断了,直接ans=ans+(n-j-1)*temp2;优化

#include<stdio.h>
using namespace std;
int mod=10e8+7;
int gcd(int x,int y)
{
    if(y>0)return gcd(y,x%y);
    return x;
}
int main()
{
    int n;
    int i,j;
    int a[500005];
    long long  temp,temp2;
    long long  ans=0;
    while(scanf("%d",&n)!=EOF){
        ans=0;
        for(i=0;i<n;i++){             //求出所有数的最小公约数,为后面的优化最解
            scanf("%d",&a[i]);
            if(i==0) temp=a[i];
            else temp=gcd(temp,a[i]);
        }
        for(i=0;i<n;i++){
                temp2=a[i];
            for(j=i;j<n;j++){
                temp2=gcd(temp2,a[j]);
                ans=ans+temp2;
                ans=ans%mod;
                if(temp2==temp){
                    ans=ans+(n-j-1)*temp2;
                    ans=ans%mod;
                    break;
                }
            }
        }
        printf("%lld\n",ans);
    }
}

攒机一时爽,一直攒机一直爽。

沉迷攒机的胡老师很快就发现,他每天只能靠吃泡面过活了。为了改善伙食,同时继续攒机大业,胡老师决定下海炒股。

胡老师有特别的炒股技巧。首先他会选定一支他看好的股票,然后永远只买这一支股票。此外,胡老师每天要么只买入股票要么只卖出股票,且出于某种不为人知的原因,胡老师手上最多只能持有 1 股的股票。胡老师每天会根据当天的股价及手上的持股数决定是买入还是卖出股票,需要注意的是,只要胡老师选择了买入或卖出,那么一定可以按当天的价格买入或卖出股票。

炒股需要本金,但胡老师的钱都拿去攒机了,于是他去找 CC 借了一大笔钱(这笔钱可以视为无穷多),并约定 n 天之后归还。另一方面,为最大化 n 天内的收益,胡老师通过不为人知的 py 交易获取了接下来 n 天每天的股票价格。

在一开始,胡老师手上没有持有股票。胡老师想知道,在n天之后他最多能靠炒股赚多少钱。

输入描述:

第一行是一个整数n (1≤n≤5×105)n (1≤n≤5×105),表示天数。

接下来 n 行给出了接下来 n 天内胡老师看好的股票每天的价格,其中第 i 行是一个整数 ai (1≤ai≤106)ai (1≤ai≤106),表示该股票在第 i 天的价格。

输出描述:

输出一行一个整数 ans,表示 n 天之后胡老师最多能赚的钱数。

示例1

 

输入

5

1

3

2

6

4

输出

6

 

题意,这是一道贪心的题目,首先,如果第n天比第n-1天的价格要多,则卖出去。可以推到如果一直高就一直买,但是如果不高就会在前一天卖掉。结合生活规律可以推出。

结合生活规律

结合生活规律

结合生活规律

 

坑:记住了答案要用long long

#include<stdio.h>
#include<iostream>
using namespace std;
int main()
{
    int n;
    int i,j;
    int a[500050];
    long long ans=0;
    while(scanf("%d",&n)!=EOF){
        ans=0;
        for(i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        for(i=1;i<n;i++){
            if(a[i]>a[i-1]){
                ans=ans+a[i]-a[i-1];
            }
        }
        printf("%lld\n",ans);
    }
}

 

Guess you like

Origin blog.csdn.net/xxf_is_girl_gad/article/details/89483651