CCF-CSP 201612 赛题训练

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF-CSP 201612 赛题训练相关的知识,希望对你有一定的参考价值。

CCF-CSP 201612 赛题训练

【CCF CSP-20161201】中间数

题意概述

在一个整数序列 a 1 , a 2 , ⋯   , a n a_1,a_2,\\cdots,a_n a1,a2,,an中,如果存在某个数,大于它的整数数量等于小于它的整数数量,则称其为中间数。在一个序列中,可能存在多个下标不相同的中间数,这些中间数的值是相同的。
给定一个整数序列,请找出这个整数序列的中间数的值。

输入输出格式

输入的第一行包含了一个整数 n,表示整数序列中数的个数。第二行包含 n 个正整数,依次表示 a 1 , a 2 , ⋯   , a n a_1,a_2,\\cdots,a_n a1,a2,,an

如果约定序列的中间数存在,则输出中间数的值,否则输出-1,表示不存在中间数。

数据规模

1 ≤ n ≤ 1000 , 1 ≤ a i ≤ 1000 1\\le n\\le1000,1\\le a_i\\le1000 1n1000,1ai1000

方法一:排序去重

排序似乎是必要的,对输入数据进行排序之后再进行处理,比较方便一些。需要略微考虑一下输入数据个数是奇数还是偶数。

/* CCF201612-1 中间数 */

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1000;
int a[N];

int main()

    int n, mid, leftcount, rightcount;

    // 输入数据
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];

    // 排序
    sort(a, a + n);

    // 找出中间数
    mid = n / 2;
    leftcount = mid;
    rightcount = n - mid - 1;
    // 去掉左边与中间相同值数的个数
    for (int i = mid - 1; i >=0; i--)
        if (a[i] == a[mid]) leftcount--;
        else break;
    // 去掉右边与中间相同值数的个数
    for (int i = mid + 1; i < n; i++)
        if (a[i] == a[mid]) rightcount--;
        else break;

    // 输出结果
    if(leftcount == rightcount)
        cout << a[mid] << endl;
    else
        cout << -1 << endl;

    return 0;

方法二:不排序版

不排序版,空间换时间,时间复杂度O(n)

利用桶计数的方法,记录数值的分布次数。

求出小于某一数j的个数,用n减去左边数,判断是否相等。

#include<bits/stdc++.h>
using namespace std;

int main() 
    int n, x;
    cin >> n;
    int a[1001];
    fill(a, a+1001, 0);
    for (int i = 0; i < n; i++) 
        cin >> x;
        a[x]++;  // 统计x次数
    
    int j = 1, sum = 0;  // sum记录小于j的个数
    while (sum <= n/2)   // 求出对半分的中间值
        sum += a[j++];
      // sum > n/2 大于一半时多加了结果
    sum -= a[--j];  // 减去多加的
    if (sum == (n-sum-a[j]))  //  //若num(小于j)=num(大于j) 
        cout << j << endl; 
    else 
        cout << -1 << endl;
    return 0;

代码来源Link

算法设计

显然,如果存在这样的中间数,则该中间数一定是序列的中位数。可以先将读入的序列排序。这样可以很轻松地找到中位数,那么如何判断这个序列中小于中位数和大于中位数的数的个数是否相等呢?由于排序后的序列是一个有序序列,我们可以使用泛型算法库中的 equal_range 算法,它可以返回两个迭代器,第一个指向序列中第一个大于等于中位数的数的位置,第二个指向序列中第一个大于中位数的数的位置,那么通过这两个迭代器就可以得出序列中小于中位数和大于中位数的数的个数了。

C++代码

#include <bits/stdc++.h>
using namespace std;
using gg = long long;
int main() 
    ios::sync_with_stdio(false);
    cin.tie(0);
    gg ni;
    cin >> ni;
    vector<gg> ai(ni);
    for (gg& i : ai) 
        cin >> i;
    
    sort(ai.begin(), ai.end());
    gg t = ai[ai.size() / 2];
    auto p = equal_range(ai.begin(), ai.end(), t);
    cout << (p.first - ai.begin() == ai.end() - p.second ? t : -1);
    return 0;

【CCF CSP-20161201】工资计算

题目

小明的公司每个月给小明发工资,而小明拿到的工资为交完个人所得税之后的工资。假设他一个月的税前工资(扣除五险一金后、未扣税前的工资)为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。

直接保留模拟所有工资情况,满足则输出,100为步数计算即可!

#include<stdio.h>
#define MAXN 200000
int main()
    int T;
    scanf("%d",&T);
    if(T<=3500) printf("%d\\n",T);
    else for(int S=3600;S<=MAXN;S+=100)
        int A=S-3500;
        int tax=0;
        if(A>1500) tax+=1500*0.03;
        else tax+=A*0.03;goto end;
        if(A>4500) tax+=3000*0.10;
        else tax+=(A-1500)*0.10;goto end;
        if(A>9000) tax+=4500*0.20;
        else tax+=(A-4500)*0.20;goto end;
        if(A>35000) tax+=26000*0.25;
        else tax+=(A-9000)*0.25;goto end;
        if(A>55000) tax+=20000*0.30;
        else tax+=(A-35000)*0.30;goto end;
        if(A>80000) tax+=25000*0.35;
        else tax+=(A-55000)*0.35;goto end;
        tax+=(A-80000)*0.45;

        end:
            if(S-tax==T)
                printf("%d\\n",S);
                break;
            
    
    return 0;

评论区的代码:

#include <iostream>
#include <cstdio>
using namespace std;
 
const int T = 100000;
 
int getTax(int pre_tax) 
	int tax = 0;
	if (pre_tax <= 3500) 
		tax = 0;
	 else 
		int a = pre_tax - 3500;
		if (a < 1500) 
			tax = a * 0.03;
		 else if (a < 4500) 
			tax = 45 + (a - 1500) * 0.1;
		 else if (a < 9000) 
			tax = 345 + (a - 4500) * 0.2;
		 else if (a < 35000) 
			tax = 345 + 900 + (a - 9000) * 0.25;
		 else if (a < 55000) 
			tax = 345 + 900 + 6500 + (a - 35000) * 0.3;
		 else if (a < 80000) 
			tax = 345 + 900 + 6500 + 6000 + (a - 55000) * 0.35;
		 else 
			tax = 345 + 900 + 6500 + 6000 + 8750 + (a - 80000) * 0.45;
		
	
 
	return tax;

 
int main() 
	int post_tax;
	cin >> post_tax;
 
	int pre_tax = 1;
	while (pre_tax++) 
		if (post_tax == pre_tax - getTax(pre_tax) && pre_tax % 100 == 0) 
//			printf("t=%d, getTax(%d)=%d\\n", t, pre_tax, getTax(pre_tax));
			cout << pre_tax << endl;
			break;
		
	
 
	return 0;

// 一起学习呀

大佬代码:打表法(看不懂)Link

加油!

感谢!

努力!

以上是关于CCF-CSP 201612 赛题训练的主要内容,如果未能解决你的问题,请参考以下文章

CCF-CSP 201604 赛题训练

CCF-CSP 201609 赛题训练

CCF-CSP 201709 赛题训练

CCF-CSP 202203 赛题训练

CCF-CSP 201909 赛题训练

CCF-CSP 201812 赛题训练