CCF 2016 真题 持续更新

中间数

描述

问题描述
  在一个整数序列a1, a2, …, an中,如果存在某个数,大于它的整数数量等于小于它的整数数量,则称其为中间数。在一个序列中,可能存在多个下标不相同的中间数,这些中间数的值是相同的。
  给定一个整数序列,请找出这个整数序列的中间数的值。
输入格式
  输入的第一行包含了一个整数n,表示整数序列中数的个数。
  第二行包含n个正整数,依次表示a1, a2, …, an。
输出格式
  如果约定序列的中间数存在,则输出中间数的值,否则输出-1表示不存在中间数。
样例输入
6
2 6 5 6 3 5
样例输出
5
样例说明
  比5小的数有2个,比5大的数也有2个。
样例输入
4
3 4 6 7
样例输出
-1
样例说明
  在序列中的4个数都不满足中间数的定义。
样例输入
5
3 4 6 6 7
样例输出
-1
样例说明
  在序列中的5个数都不满足中间数的定义。
评测用例规模与约定
  对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ ai ≤ 1000。

分析

这个还是不同于找中位数的,其实也不要想太多,就按题目的要求,排序后老老实实从中间向两边找,计数到左右不同的数之后,再计数剩下的数是否相同

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
int num[1005];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i =0;i<n;i++)
        scanf("%d",&num[i]);

        sort(num,num+n);
        int mid = n/2;
        int stand = num[mid];
        int left=mid,right=mid;

        while(left>0&&num[left]==stand)
        {
        left --;
        }

        while(right<n-1 && num[right]==stand)right ++;

        int lpart = left+1, rpart = n-right;

        if(lpart == rpart)printf("%d\n",stand);
        else printf("-1\n");
    }
}

工资计算

描述

问题描述
  小明的公司每个月给小明发工资,而小明拿到的工资为交完个人所得税之后的工资。假设他一个月的税前工资(扣除五险一金后、未扣税前的工资)为S元,则他应交的个人所得税按如下公式计算:
  1) 个人所得税起征点为3500元,若S不超过3500,则不交税,3500元以上的部分才计算个人所得税,令A=S-3500元;
  2) A中不超过1500元的部分,税率3%;
  3) A中超过1500元未超过4500元的部分,税率10%;
  4) A中超过4500元未超过9000元的部分,税率20%;
  5) A中超过9000元未超过35000元的部分,税率25%;
  6) A中超过35000元未超过55000元的部分,税率30%;
  7) A中超过55000元未超过80000元的部分,税率35%;
  8) A中超过80000元的部分,税率45%;
  例如,如果小明的税前工资为10000元,则A=10000-3500=6500元,其中不超过1500元部分应缴税1500×3%=45元,超过1500元不超过4500元部分应缴税(4500-1500)×10%=300元,超过4500元部分应缴税(6500-4500)×20%=400元。总共缴税745元,税后所得为9255元。
  已知小明这个月税后所得为T元,请问他的税前工资S是多少元。
输入格式
  输入的第一行包含一个整数T,表示小明的税后所得。所有评测数据保证小明的税前工资为一个整百的数。
输出格式
  输出一个整数S,表示小明的税前工资。
样例输入
9255
样例输出
10000
评测用例规模与约定
  对于所有评测用例,1 ≤ T ≤ 100000。

分析

这题乍一看挺简单的,本来的思路是手算出对应的T的范围,然后将输入的T按照范围换元成S,结果算着算着就晕了……
看了网上的参考,充分体会到了什么叫程序员数学不好,,真的没必要计算出具体的数,只要列出公式,找出抽象的共性和规律,然后剩下的交给计算机来算就可以了
还是列出式子,表达出S的表达式,然后就直接用S的范围来圈定就可以,感觉思路十分新奇
代码如下

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
    float rate[]={0.03,0.1,0.2,0.25,0.3,0.35,0.45};
    float revenue[] = {1500*rate[0],(4500-1500)*rate[1],(9000-4500)*rate[2],(35000-9000)*rate[3],(55000-35000)*rate[4],(80000-55000)*rate[5]};
int main()
{
    int T;

    while(~scanf("%d",&T)){

    float S=(float)T,res=(float)T;

    if(T>3500)
    {
    //其实列出两三个就知道规律是什么了
        S =( T - rate[0]*3500)/(1-rate[0]);
        if( S-3500>0 && S-3500<=1500)res = S;

        S = (T + revenue[0] - rate[1]*(3500+1500))/(1-rate[1]);
        if( S-3500 > 1500 && S-3500<=4500)res = S;

        S = (T + revenue[0]+revenue[1] - rate[2]*(3500+4500))/(1-rate[2]);
        if(S - 3500 >4500 && S-3500 <=9000)res = S;

        S = (T + revenue[0]+revenue[1]+revenue[2] - rate[3]*(3500+9000))/(1-rate[3]);
        if(S - 3500 > 9000 && S- 3500 <=35000)res = S;

        S = (T+revenue[0]+revenue[1]+revenue[2] + revenue[3] - rate[4]*(3500+35000))/(1-rate[4]);
        if(S - 3500 >35000 && S- 3500 <=55000)res = S;

        S = (T +revenue[0]+ revenue[1]+revenue[2] + revenue[3] + revenue[4]- rate[5]*(3500+55000))/(1-rate[5]);
        if(S-3500 > 55000 && S-3500 <=80000)res = S;

        S = (T +revenue[0]+ revenue[1]+revenue[2] + revenue[3] + revenue[4] + revenue[5] - rate[6]*(3500 + 80000))/(1-rate[6]);
        if(S - 3500 >80000)res = S;

    }
    int ans = (int)res;
    printf("%d\n",ans);
    }
}

火车购票

描述

问题描述
  请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配。
  假设一节车厢有20排、每一排5个座位。为方便起见,我们用1到100来给所有的座位编号,第一排是1到5号,第二排是6到10号,依次类推,第20排是96到100号。
  购票时,一个人可能购一张或多张票,最多不超过5张。如果这几张票可以安排在同一排编号相邻的座位,则应该安排在编号最小的相邻座位。否则应该安排在编号最小的几个空座位中(不考虑是否相邻)。
  假设初始时车票全部未被购买,现在给了一些购票指令,请你处理这些指令。
输入格式
  输入的第一行包含一个整数n,表示购票指令的数量。
  第二行包含n个整数,每个整数p在1到5之间,表示要购入的票数,相邻的两个数之间使用一个空格分隔。
输出格式
  输出n行,每行对应一条指令的处理结果。
  对于购票指令p,输出p张车票的编号,按从小到大排序。
样例输入
4
2 5 4 2
样例输出
1 2
6 7 8 9 10
11 12 13 14
3 4
样例说明
  1) 购2张票,得到座位1、2。
  2) 购5张票,得到座位6至10。
  3) 购4张票,得到座位11至14。
  4) 购2张票,得到座位3、4。
评测用例规模与约定
  对于所有评测用例,1 ≤ n ≤ 100,所有购票数量之和不超过100。

分析

模拟这个思路就好了,数量级都不大,就正常思路就可以。用数组表示,用101以后的数表示已经卖出的票

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
int tickets[105][10];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int cnt = 1;
        for(int i = 1;i<=n;i++)
        for(int j = 1;j<=5;j++)
        tickets[i][j] = cnt++;
        int num;

        for(int i = 0;i<n;i++)
        {
            bool flag = false;
            scanf("%d",&num);
            for(int r = 1;r<=n;r++)
            {
                int c;
                for(c = 1;c<=5;c++)
                {
                    if(tickets[r][c]<101 )
                    {
                        if(6-c>=num)
                        {
                            flag = true;
                            int k = 0;
                            while(k<num){
                                printf("%d ",tickets[r][c+k]);
                                tickets[r][c+k]=105;k++;
                            }
                            printf("\n");
                            break;
                        }

                    }

                }
                if(flag)break;
            }


            if(flag == false)
            {
                int k = 0; bool flag2 = false;
                for(int r = 1;r<=n;r++)
                {
                    for(int c = 1;c<=5;c++)
                    {
                    if(tickets[r][c]<101)
                    {
                        k++;printf("%d ",tickets[r][c]);
                        tickets[r][c] = 105;
                        if(k>=num){flag2 = true;break;
                        }
                    }
                    }
                    if(flag2)break;
                }
                printf("\n");

            }

        }
    }
}

折点计数

描述

问题描述
  给定n个整数表示一个商店连续n天的销售量。如果某天之前销售量在增长,而后一天销售量减少,则称这一天为折点,反过来如果之前销售量减少而后一天销售量增长,也称这一天为折点。其他的天都不是折点。如下图中,第3天和第6天是折点。

  给定n个整数a1, a2, …, an表示销售量,请计算出这些天总共有多少个折点。
  为了减少歧义,我们给定的数据保证:在这n天中相邻两天的销售量总是不同的,即ai-1≠ai。注意,如果两天不相邻,销售量可能相同。
输入格式
  输入的第一行包含一个整数n。
  第二行包含n个整数,用空格分隔,分别表示a1, a2, …, an。
输出格式
  输出一个整数,表示折点出现的数量。
样例输入
7
5 4 1 2 3 6 4
样例输出
2
评测用例规模与约定
  所有评测用例满足:1 ≤ n ≤ 1000,每天的销售量是不超过10000的非负整数。

分析

就是求斜率好了,在斜率符号发生变化的地方就是折点;
而相邻两点的横坐标都是1,所以斜率就变成了后一个数-前一个数
统计发生符号变化的地方

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
int num[1005];
int k[1005];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i =1;i<=n;i++)
        {
            scanf("%d",&num[i]);
        }
        int pos = 0;
        for(int i = 2;i<=n;i++)
        {
            k[pos] = (num[i]-num[i-1]);
            pos ++;
        }
        int ans = 0;
        for(int i = 1;i<pos;i++)
        {
            if(k[i]*k[i-1]<0)ans++;
        }
        cout<<ans<<"\n";
    }
}

猜你喜欢

转载自blog.csdn.net/BeforeEasy/article/details/82467293