• 0827考试总结


    1.切香肠

      (kusac.pas/c/cpp)

    【问题描述】

        Jzyz的某次期中考试奖学金是由火腿肠企业赞助的,于是,奖学金变成了奖品,并且是N根长度完全相同的火腿肠。

    本次考试一共M名同学获奖,学校决定,火腿肠全部平均分配,小x因为考试成绩很好,于是被选派为分火腿肠的人。

    小x现在有一把很精确的刀,他可以一刀切掉火腿肠的任意需要的指定部分,小x现在想知道,如何用最少切的次数,完成火腿肠的分配。

    比如,现在有2根火腿肠,有6个人获奖,那么,每根火腿肠需要切2刀,这样4刀就将火腿肠等分为6等份。

    如果有3根火腿肠,4个人获奖,那么小x只需要把每根火腿肠切掉1/4,这样有3个人拿到每根的3/4,有一个人拿到3小块的1/4.这样最少3刀也能等分。

    现在你需要帮助小x完成这个任务。

    【输入】

    两个整数N和M

    【输出】

    一个整数,最少切多少次可以平分。

    【输入输出样例1】

    kusac.in

    kusac.out

    2 6

    4

    【输入输出样例2】

    kusac.in

    kusac.out

    3 4

    3

    【输入输出样例3】

    kusac.in

    kusac.out

    6 2

    0

    【数据范围】

    30%  1 ≤ N, M ≤ 16 

    100% 数据(1 ≤ N, M ≤ 100)

    题解:

    Kusac 火腿肠

    锻炼思维的一道题目,我不认为简单,我拿到这道题的时候,我想了很久很久,还是没想出来,可能我的数学思维不行。

     

    我觉得一个思考方案是,将N根火腿肠放在一起,假设是一根的话,那么切M-1刀,就肯定得到了M根。

    但是,如果要切这M-1刀中,恰好有k刀是N根火腿肠的分割处,那么就不用切了。那么恰好会有多少分割处是要切的呢?

    就是M和N的最大公约数-1次,

    所以 结论就是 M-1-(gcd(M,N)-1)= M- gcd(M,N)

     

    本道题数据量很小,求最大公约数很好求,不过我们一般求最大公约数都用欧几里得算法。

    cpp:

    #include<iostream>
    #include<cmath>
    #include<string>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    long long m,n,sum=0;
    int gcd(int a,int b)
    {
    if(b==0) return a;
    return gcd(b,a%b);
    }
    int main()
    {
    freopen("kusac.in","r",stdin);
    freopen("kusac.out","w",stdout);
    cin>>n>>m;
    sum=m-1-(gcd(m,n)-1);
    cout<<sum<<endl;
    return 0;
    }


    2.赛车

      (car.pas/c/cpp)

    【问题描述】

        Jzyz的老师们要结伴出游了,并且他们到了一个很宽阔的赛车场,并且赛车场两边的风景是极好的,所以赛车不重要,看风景最重要。

        现在jzyz有N名老师要参加看风景赛车,编号为1..N,赛车场有M条(1<=M<=N)条车道,编号为i的老师自己的车速最大为Si(1<=Si<=10^6)。

        在经历很多次模拟驾驶之后,老师们为了避免碰撞,于是规定,每条车道上,如果某位老师前面有k个老师,那么这位老师的车速上限就会下降k*D个单位,也就是说第i个老师的开车的速度不会超过Si-k*D(0<=D<=5000),当然,如果这个数是负的,这个老师的速度将是0.当然只要遵循这个规则,老师们肯定就不会发生碰撞。

        但是,最后老师们才发现,赛车场有规定,在赛道上行驶的车辆速度不得低于L(1<=L<=10^6)。

        给定所有的数据,现在请你帮老师们计算一下,最多有多少个老师可以完成比赛,并欣赏到风景。

    【输入】

           第一行四个整数N,M,D,L。

           接下来N行,每行一个整数,第i行为Si,表示第i位老师的车速上限。

    【输出】

    一个整数,最多有多少老师可以完成比赛。

    【输入输出样例】

    car.in

    car.out

    3 1 1 5
    5
    7
    5

    2

    有3个老师,1个赛道,第一个和第二个老师可以参加比赛。

    【数据范围】

       50%  保证N<=100;

       100% N<=50000,其余如题目描述

    题解:

    Car

    这道题有一个贪心的规则,不要问我怎么想出来的,我只能说是经验,或者感觉。

    不要问我怎么证明,考试的时候只要想不出反例,我们就努力去写。

    首先,肯定按照速度排序是肯定的,这个肯定能想到;

    然后,为了让更多的老师参加比赛,速度慢的肯定放前面,速度快的肯定放后面。

    那样就按照速度从小到大,依次让老师按照速度从小到大的顺序从1,2,3..M号跑道上为第一个,第二个,能参加就参加,不能参加就不参加,这样就能保证让最多的人参加。

    一个for循环的验证即可。

    这种题就是需要自己设计策略的问题,而如何设计策略,只能靠自己的建模能力和经验,如何培养建模能力和经验,除了多做题,多思考之外,我觉得反思和总结比一味的看通过率和排名要更加重要。

    对于贪心的策略的总结,将是一个永恒的话题。

    cpp:

    #include<iostream>
    #include<cmath>
    #include<string>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    const int maxn=500000;
    long long n,m,d,l,sum=0;
    long long s[maxn],road[maxn];
    void work(long long x,long long dao)
    {
    if(dao>m)
    return;
    long long speed;
    speed=x-road[dao]*d;
    if(speed>=l)
    {
    sum++;
    road[dao]++;
    return;
    }
    else
    work(x,dao+1);
    }
    int main()
    {
    freopen("car.in","r",stdin);
    freopen("car.out","w",stdout);
    ios::sync_with_stdio(false);
    cin>>n>>m>>d>>l;
    for(int i=1;i<=n;i++)
    cin>>s[i];
    memset(road,0,sizeof(road));
    sort(s+1,s+1+n);
    for(int i=1;i<=n;i++)
    {
    if(s[i]>=l)
    {
    work(s[i],1);
    }
    }
    cout<<sum<<endl;
    return 0;
    }



    3.排序

      (sort.pas/c/cpp)

    【问题描述】

        小x在学习了各种排序算法后,决定自己设计一个排序算法。

        他设计的排序算法有两种操作:

    1) 挑出某个数,将其放在序列的最前面;

    2) 挑出某个数,将其放在序列的最后面;

    现在小x想知道,在最优情况下,按上面的操作将n个数排序完毕,最少的操作次数是多少?

    给定一个序列:{8,12,25,7,15,19}

    只需要将7放在前面,25 放在后面,两个操作即可。

    【输入】

    第一行一个数N,表示有N个数需要排序。

           第二行N个整数,用空格隔开,表示要排序的N个数

    【输出】

    一个整数表示需要的操作次数。

    【输入输出样例1】

    sort.in

    sort.out

    6

    8 12 25 7 15 19

    2

    【数据范围】

          对于30% 的数据N≤50;

           对于60% 的数据N≤1 000;

           对于100% 的数据N≤100 000,且保证排序的每个数都不相同。

    题解:

    Sort 有一定思维难度

    思考,不用进行操作的数,在最终序列里是什么样子。并且这个序列自然是越长越好。

    我们需要找的是,在结果中单调递增,并且在原序列 中 以这个顺序存在的最长的一段。

    比如样例:

    812 25 7 15 19

    我们发现 8  12 15  19 是最长的,所以,不需要改变位置的是4个数,需要改变的是 6-4=2个。

    所以,本题就是找到一个排完序后是连续的,且在原序列中下标也是递增的最长的序列。

    所以,本题就是一个排序+统计的过程。

    具体如下:

    1  2  3  4  5  6

    812  25 7 15 19

    排序之后,位置是

    23  6 1   4   5

    具体统计排序前在其前面,且排序后也在其前面并且连续的序列的长度为

    12  1 1   3    4

    所以最长的长度为  4。

    cpp:

    先sort,然后找出最大升序列 n-max为结果。


  • 相关阅读:
    mySQL优化方案
    java之自动过滤提交文本中的html代码script代码
    java小技术之生成二维码
    微信扫码支付功能详细教程————Java
    java实现发送邮件服务器,SMTP协议发送邮件
    『重构--改善既有代码的设计』读书笔记----序
    Linux导航神器-----autojump
    绘图时,根据size()和自定义rect编程的区别
    Qt中如何在QCursor移动的时候不触发moveEvent
    Qt远程机开发时光标注意问题
  • 原文地址:https://www.cnblogs.com/zyker/p/5879204.html
Copyright © 2020-2023  润新知